k8s集群Canal的网络控制 原
  1 简介
  
  直接上干货
  
  public class DispatcherServlet extends HttpServlet {
  
  private Properties contextConfigProperties = new Properties();
  
  private List<String> classNames = new ArrayList<>();
  
  private Map<String, Object> ioc = new HashMap<String, Object>();
  
  private Map<String, Method> handlerMappings = new HashMap<>();
  
  /**
  
  *
  
  */
  
  private static final long serialVersionUID = 1L;
  
  @Override
  
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  
  this.doPost(req, resp);
  
  }
  
  @Override
  
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  
  try {
  
  dispatcher(req,resp);
  
  } catch (Exception e) {
  
  resp.getWriter().write("500 Server has an error"+Arrays.toString(e.getStackTrace()));
  
  }
  
  }
  
  private void dispatcher(HttpServletRequest req, HttpServletResponse resp) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
  
  if (this.handlerMappings.isEmpty()) {
  
  return;
  
  }
  
  String url = req.getRequestURI();
  
  String contextPath = req.getContextPath();
  
  url.replace(contextPath, "").replaceAll("/+", "/");
  
  if (!this.handlerMappings.containsKey(url)) {
  
  resp.getWriter().write("404 Page Not Found!    ");
  
  return;
  
  }
  
  Method method = this.handlerMappings.get(url);
  
  Map<String,String[]> parameterMap = req.getParameterMap();
  
  String beanName = this.lowerFirstLetter(method.getDeclaringClass().getSimpleName());
  
  Object obj = this.ioc.get(beanName);
  
  if (!parameterMap.containsKey("name")) {
  
  resp.getWriter().write("handerMapping Not Found!");
  
  return;
  
  }
  
  method.invoke(obj, new Object[] {req,resp,parameterMap.get("name")[0]});
  
  }
  
  @Override
  
  public void init(ServletConfig config) throws ServletException {
  
  //加载配置
  
  loadConfig(config.getInitParameter("contextConfigLocation"));
  
  //扫描指定包下的所有类
  
  scannerClass(this.contextConfigProperties.getProperty("scanPackage"));
  
  //初始化容器
  
  initIoc();
  
  //自动注入
  
  autoWiredInstance();
  
  //初始化处理映射
  
  initHanderMapping();
  
  System.out.println("mvc init over...");
  
  }
  
  private void initHanderMapping() {
  
  if (this.ioc.isEmpty()) {
  
  return;
  
  }
  
  try {
  
  for (Map.Entry<String, Object> en : this.ioc.entrySet()) {
  
  boolean present = en.getValue().getClass().isAnnotationPresent(Controller.class);
  
  if (present) {
  
  StringBuffer baseUrl = new StringBuffer();
  
  RequestMapping requestMapping = en.getValue().getClass().getAnnotation(RequestMapping.class);
  
  baseUrl.append(requestMapping.value());
  
  Method[] methods = en.getValue().getClass().getMethods();
  
  for (Method method : methods) {
  
  if (method.isAnnotationPresent(RequestMapping.class)) {
  
  RequestMapping mapping = method.getAnnotation(RequestMapping.class);
  
  String fullUrl = ("/"+baseUrl.append("/").append(mapping.value().trim()).toString()).replaceAll("/+", "/");
  
  this.handlerMappings.put(fullUrl, method);
  
  }
  
  }
  
  }
  
  }
  
  } catch (Exception e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  private void autoWiredInstance() {
  
  if (this.ioc.isEmpty()) {
  
  return;
  
  }
  
  try {
  
  for (Map.Entry<String, Object> en : this.ioc.entrySet()) {
  
  Field[] fields = en.getValue().getClass().getDeclaredFields();
  
  for (Field field : fields) {
  
  if (field.isAnnotationPresent(Autowired.class)) {
  
  Autowired autowired = field.getAnnotation(Autowired.class);
  
  String beanName = autowired.value();
  
  if ("".equals(beanName)) {
  
  beanName = field.getType().getName();
  
  }
  
  field.setAccessible(true);
  
  field.set(en.getValue(), this.ioc.get(beanName));
  
  }
  
  }
  
  }
  
  } catch (Exception e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  private void initIoc() {
  
  if (this.classNames.isEmpty()) {
  
  return;
  
  }
  
  try {
  
  for (String className : classNames) {
  
  Class<?> clazz = Class.forName(className);
  
  if (clazz.isAnnotationPresent(Controller.class)||clazz.isAnnotationPresent(Service.class)) {
  
  Object newInstance = clazz.newInstance();
  
  String simpleName = lowerFirstLetter(clazz.getSimpleName());
  
  if (clazz.getAnnotation(Controller.class)!=null) {
  
  String value = clazz.getAnnotation(Controller.class).value();
  
  if ("".equals(value.trim())) {
  
  this.ioc.put(simpleName, newInstance);
  
  }else {
  
  this.ioc.put(value, newInstance);
  
  }
  
  }else if (clazz.getAnnotation(Service.class)!=null) {
  
  String value = clazz.getAnnotation(Service.class).value();
  
  handleAnnotation(clazz,value, newInstance);
  
  }else if (clazz.getAnnotation(Dao.class)!=null) {
  
  String value = clazz.getAnnotation(Dao.class).value();
  
  handleAnnotation(clazz,value, newInstance);
  
  }else {
  
  this.ioc.put(simpleName, clazz.newInstance());
  
  }
  
  }else {
  
  continue;
  
  }
  
  }
  
  } catch (Exception e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  private void handleAnnotation(Class<?> clazz,String annotationValue, Object newInstance) throws Exception {
  
  if ("".equals(annotationValue.trim())) {
  
  Class<?>[] interfaces = clazz.getInterfaces();
  
  for (Class<?> i : interfaces) {
  
  if (this.ioc.containsKey(i.getName())) {
  
  throw new Exception("the beanName:"+i.getName()+",has samed");
  
  }
  
  this.ioc.put(i.getName(), newInstance);
  
  }
  
  }else {
  
  this.ioc.put(annotationValue, newInstance);
  
  }
  
  }
  
  private void scannerClass(String scanPackage) {
  
  URL url = this.getClass().getClassLoader().getResource(File.separator+scanPackage.replaceAll(".", File.separator));
  
  File dir = new File(url.getFile());
  
  for (File file : dir.listFiles()) {
  
  if (file.isDirectory()) {
  
  scannerClass(scanPackage+"."+file.getName());
  
  }else {
  
  if (!file.getName().contains(".class")) {
  
  continue;
  
  }
  
  String className = (scanPackage+"."+file.getName().replaceAll("class", "")).trim();
  
  this.classNames.add(className);
  
  Canal 是calico和flannel的结合,我们因为Calico不仅能够提供很好的网络性能,还能有网络规则控制,但是我们很多时候使用的Flannel网络,他的缺点就是没有网络控制只能提供网络服务,所以Canal诞生了,为Falanel提供了网络控制。
  
  网络策略 控制出站: egress 控制进站: ingress 可以以ip地址块定义规则,也可以基于命名空间规则定义,还可以对pod定义规则
  
  2 部署Canal
  
  curl \
  
  https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/canal/canal.yaml \
  
  -O
  
  kubectl apply -f canal.yaml
  
  1)canal默认控制的是10.244.0.0/16 ,如果你在安装k8s集群是设置的pod网络不是此段网络,则你需要修改配置文件
  
  2)我们采用的和k8s集群公用etcd的方式创建
  
  查看创建的pod
  
  # kubectl get pods -n kube-system
  
  NAME                                    READY   STATUS    RESTARTS   AGE
  
  canal-9lmw8                             2/2     Running   0          4m50s
  
  canal-ln6kg                             2/2     Running   0          4m50s
  
  canal-mx6tn                             2/2     Running   0          4m50s
  
  coredns-fb8b8dccf-lfbkh                 1/1     Running   2          10d
  
  coredns-fb8b8dccf-t2kdz                 1/1     Running   2          10d
  
  etcd-master-1                           1/1     Running   2          10d
  
  kube-apiserver-master-1                 1/1     Running   2          10d
  
  kube-controller-manager-master-1        1/1     Running   2          10d
  
  kube-flannel-ds-amd64-df7gk             1/1     Running   3          9d
  
  kube-flannel-ds-amd64-dzxfd             1/1     Running   3          9d
  
  kube-flannel-ds-amd64-mgw2m             1/1     Running   2          9d
  
  kube-proxy-47d6q                        1/1     Running   2          10d
  
  kube-proxy-jztrs                        1/1     Running   3          10d
  
  kube-proxy-rt4xx                        1/1     Running   3          10d
  
  kube-scheduler-master-1                 1/1     Running   2          10d
  
  kubernetes-dashboard-5f7b999d65-8h79h   1/1     Running   0          21h
  
  3 创建两个实验的空间
  
  kubectl create namespace shengchan
  
  kubectl create namespace test
  
  4 创建网络规则测试
  
  默认ingress 和 engress可以一起使用,当这两规则同时存在那么将使用policyTypes做具体的规则指向
  
  例如:创建一个policy默认拒绝所有在空间shengchan的入站规则
  
  # cat ingress-deny.yaml
  
  apiVersion: networking.k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: deny-all-ingress
  
  namespace: shengchan
  
  spec:
  
  podSelector: {}
  
  policyTypes:
  
  - Ingress
  
  kubectl apply ingress-deny.yaml
  
  创建一组属于shengchan空间的pod
  
  # cat pod-networkpolicy1.yaml
  
  apiVersion: v1
  
  kind: Pod
  
  metadata:
  
  name: pod-test
  
  spec:
  
  containers:
  
  - name: pod-test-policy
  
  image: nginx:1.10
  
  kubectl apply -f pod-networkpolicy1.yaml  -n shengchan
  
  创建一组属于test空间的pod
  
  kubectl apply -f pod-networkpolicy1.yaml  -n test
  
  分别查看两组pod的IP地址
  
  # kubectl get pods -o wide  -n shengchan
  
  NAME       READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
  
  pod-test   1/1     Running   0          16s   10.244.1.2   node2   <none>           <none>
  
  [root@master-1 ~]# kubectl get pods -o www.mmingyLgw.com wide  -n test
  
  NAME       READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
  
  pod-test   1/1     Running   0          9s    10.244.2.2   node1   <none>           <none>
  
  在宿主机上面分别ping这两个ip
  
  # ping 10.244.1.2 -c 1
  
  PING 10.244.1.2 (10.244.1.2) 56(84) bytes of data.
  
  ^C
  
  --- 10.244.1.2 ping statistics ---
  
  1 packets transmitted, 0 received, 100% packet loss, time 0ms
  
  # ping 10.244.2.2 -c 1
  
  PING 10.244.2.2 (10.244.2.2) 56(84) bytes of data.
  
  64 bytes from 10.244.2.2: icmp_seq=1 ttl=63 time=0.660 ms
  
  --- 10.244.2.2 ping statistics ---
  
  1 packets transmitted, 1 received, 0% packet loss, time 0ms
  
  rtt min/avg/max/mdev = 0.660/0.660/0.660/0.000 ms
  
  此时发现属于shengchan空间的pod是被拒绝访问的,属于test空间的pod正常访问
  
  此时我们是基于名称空间级别的入站网络访问策略
  
  5 将上面的默认拒绝策略放行
  
  修改配置文件
  
  apiVersion: networking.www.tianscpt.com  k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: deny-all-ingress
  
  namespace: shengchan
  
  spec:
  
  podSelector: {www.yunsengyule.com}
  
  ingress:
  
  - {}
  
  policyTypes:
  
  - Ingress
  
  kubectl apply -f ingress-deny.yaml
  
  再次测试10.244.1.2
  
  [root@master-1 ~]# curl -I 10.244.1.2
  
  HTTP/1.1 200 OK
  
  Server: nginx/1.10.3
  
  Date: Sat, 27 Apr 2019 16:58:04 GMT
  
  Content-Type: text/html
  
  Content-Length: 612
  
  Last-Modified: Tue, 31 Jan 2017 15:01:11 GMT
  
  Connection: keep-alive
  
  ETag: "5890a6b7-264"
  
  Accept-Ranges: bytes
  
  [root@master-1 ~]# curl yunshenggw.cn/-I 10.244.2.2
  
  HTTP/1.1 200 OK
  
  Server: nginx/1.10.3
  
  Date: Sat, 27 Apr 2019 16:58:07 GMT
  
  Content-Type:www.douniu2.cc text/html
  
  Content-Length: 612
  
  Last-Modified: Tue, 31 Jan 2017 15:01:11 GMT
  
  Connection: keep-alive
  
  ETag: "5890a6b7-264"
  
  Accept-Ranges: bytes
  
  说明我们的网络策略放行成功
  
  6 放行特定的入站
  
  以标签的形式进行划分pod入站规则是否被放行
  
  1)回复默认拒绝所有
  
  [root@master-1 ~]# cat ingress-deny.yaml
  
  apiVersion: networking.k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: deny-all-ingress
  
  namespace: shengchan
  
  spec:
  
  podSelector: {www.baihuiyulep.cn}
  
  policyTypes:
  
  - Ingress
  
  kubectl apply www.mumingyue.cn-f ingress-deny.yaml
  
  2)给shengchan pod打一个标签
  
  kubectl label pods pod-test app=www.dayuzaixianyL.cn hello -n shengchan
  
  3)创建一个新的规则
  
  # vim ingress-allow.yml
  
  apiVersion: networking.k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: allow-hello-ingress
  
  namespace: shengchan
  
  spec:
  
  podSelector:
  
  matchLabels:
  
  app: hello
  
  ingress:
  
  - from:
  
  - ipBlock:
  
  cidr: 10.244.0.0/16
  
  except:
  
  - 10.244.2.2/32
  
  ports:
  
  - protocol: TCP
  
  port: 80
  
  解释: 我们重新定义了一个policy,通过标签匹配到我们已有的pod(我们一已有的pod是拒绝所有访问的),定义ingres规则,如果不通过from方式定义默认是所有网段都可以访问到拥有这个标签的pod为了测试我们使用from方式去拒绝10.244.0.0但是会放行10.244.2.2因为我们有这个ip的pod创建万郴更可以进行测试ports就是指定特定开放的端口
  
  4)创建之前进行访问测试
  
  # kubectl get pods -n shengchan -o wide
  
  NAME       READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
  
  pod-test   1/1     Running   0          62m   10.244.1.2   node2   <none>           <none>
  
  # curl 10.244.1.2
  
  说明无法访问
  
  5)创建之后测试
  
  kubectl apply -f ingress-allow.yml
  
  [root@master-1 ~]# curl -I 10.244.1.2
  
  HTTP/1.1 200 OK
  
  Server: nginx/1.10.3
  
  Date: Sat, 27 Apr 2019 17:32:15 GMT
  
  Content-Type: text/html
  
  Content-Length: 612
  
  Last-Modified: Tue, 31 Jan 2017 15:01:11 GMT
  
  Connection: keep-alive
  
  ETag: "5890a6b7-264"
  
  Accept-Ranges: bytes
  
  说明已经放行
  
  至于对于10.244.0.0网段的限制有兴趣可以测试一下
  
  6 egress出站规则
  
  1)设置一个拒绝所有出站policy
  
  cat egress.yml
  
  apiVersion: networking.k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: deny-all-egress
  
  namespace: test
  
  spec:
  
  podSelector: {}
  
  policyTypes:
  
  - Egress
  
  kubectl apply -f egress.yml
  
  2)创建一个test命名空间下的pods
  
  kubectl apply -f pod-networkpolicy1.yaml -n test
  
  3)查看podIP并进去容器去测试ping一个正常的podip
  
  [root@master-1 ~]# kubectl get pods -o wide
  
  NAME                        READY   STATUS    RESTARTS   AGE    IP            NODE    NOMINATED NODE   READINESS GATES
  
  net-test-5764c456cb-2c9df   1/1     Running   24         24h    10.244.2.22   node1   <none>           <none>
  
  net-test-5764c456cb-ng6vh   1/1     Running   46         6d5h   10.244.1.21   node2   <none>           <none>
  
  [root@master-1 www.mhylpt.com/~]# kubectl get pods -o wide -n test
  
  NAME       READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
  
  pod-test   1/1     Running   0          86m   10.244.2.2   node1   <none>           <none>
  
  kubectl exec -it pod-test -n test -- /bin/bash
  
  root@pod-test:/# ping 10.244.1.21
  
  PING 10.244.1.21 (10.244.1.21): 56 data bytes
  
  ^C--- 10.244.1.21 ping statistics ---
  
  3 packets transmitted, 0 packets received, 100% packet loss
  
  说明此时已经应用策略
  
  4)修改配置文件放行所有出站
  
  # cat egress.yml
  
  apiVersion: networking.k8s.io/v1
  
  kind: NetworkPolicy
  
  metadata:
  
  name: deny-all-egress
  
  namespace: test
  
  spec:
  
  podSelector: {}
  
  egress:
  
  - {}
  
  policyTypes:
  
  - Egress
  
  kubectl apply -f egress.yml
  
  测试:
  
  root@pod-test:/# ping 10.244.1.21 -c 1
  
  PING 10.244.1.21 (10.244.1.21): 56 data bytes
  
  64 bytes from 10.244.1.21: icmp_seq=0 ttl=62 time=0.939 ms
  
  --- 10.244.1.21 ping statistics ---
  
  1 packets transmitted, 1 packets received, 0% packet loss
  
  round-trip min/avg/max/stddev = 0.939/0.939/0.939/0.000 ms
  
  此时说明已经放行成功
  
  7 更加复杂的policy规则需要根据不同的环境规划进行深入探究,其所有都规则都体现在配置文件中
k8s集群Canal的网络控制 原的更多相关文章
- Kubernetes全栈架构师(二进制高可用安装k8s集群扩展篇)--学习笔记
		
目录 二进制Metrics&Dashboard安装 二进制高可用集群可用性验证 生产环境k8s集群关键性配置 Bootstrapping: Kubelet启动过程 Bootstrapping: ...
 - k8s集群搭建过程详解
		
准备工作 安装CentOS7虚拟机 略 安装Docker 略 关闭CentOS7自带的防火墙服务 systemctl disable firewalld systemctl stop firewall ...
 - 基于 kubeadm 部署单控制平面的 k8s 集群
		
单控制平面不符合 HA 要求,但用于开发/测试环境不会有任何问题,如果资源足够的话(10台以上服务器,3台用于APIserver.3台用于 etcd 存储.至少3台用于工作节点.1台作为负载均衡),可 ...
 - Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列之flanneld网络介绍及部署(三)
		
0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 一.flanneld介绍 ...
 - K8s二进制部署单节点 etcd集群,flannel网络配置   ——锥刺股
		
K8s 二进制部署单节点 master --锥刺股 k8s集群搭建: etcd集群 flannel网络插件 搭建master组件 搭建node组件 1.部署etcd集群 2.Flannel 网络 ...
 - k8s集群StatefulSets的Pod调度查询丢失问题?
		
k8s集群StatefulSets的Pod调度查询丢失问题? 考点之简单介绍下StatefulSets 和 Deployment 之间有什么本质区别?特定场景该如何做出选择呢? 考点之你能辩证的说说看 ...
 - 1.还不会部署高可用的kubernetes集群?看我手把手教你使用二进制部署v1.23.6的K8S集群实践(上)
		
公众号关注「WeiyiGeek」 设为「特别关注」,每天带你玩转网络安全运维.应用开发.物联网IOT学习! 本章目录: 0x00 前言简述 0x01 环境准备 主机规划 软件版本 网络规划 0x02 ...
 - Centos7 安装部署Kubernetes(k8s)集群
		
目录 一.系统环境 二.前言 三.Kubernetes 3.1 概述 3.2 Kubernetes 组件 3.2.1 控制平面组件 3.2.2 Node组件 四.安装部署Kubernetes集群 4. ...
 - k8s重要概念及部署k8s集群(一)--技术流ken
		
重要概念 1. cluster cluster是 计算.存储和网络资源的集合,k8s利用这些资源运行各种基于容器的应用. 2.master master是cluster的大脑,他的主要职责是调度,即决 ...
 
随机推荐
- 初步认识Swiper_前端交互控制神器_滚动3D切换等特效简单制作
			
前言: 本人在项目的工作中负责研发,页面及交互基本都是交给前端去做的.以前前端写的东西大概都知道,都是一些JS,CSS和HTML等的一些基本控制,都懂!但是今天前端突然做了一个具有特殊效果的DOM:页 ...
 - The openssl extension is required for SSL/TLS protection but is not available
			
今天使用composer update发现报错:The openssl extension is required for SSL/TLS protection but is not availabl ...
 - SpringEl表达式(转)
			
什么是SpringEL? Spring3中引入了Spring表达式语言—SpringEL,SpEL是一种强大,简洁的装配Bean的方式,他可以通过运行期间执行的表达式将值装配到我们的属性或构造函数当中 ...
 - html meta标签使用及属性介绍
			
自学前端开始,我对meta标签接触不多,主要把精力都集中在能显示出来的标签上,比如span.button.h1等等.有时候去查看一些知名网站的源码,发现head标签里有一大摞的meta. 今天就来学习 ...
 - ES6基础
			
一.新增命令let/const ①:let命令 1.let命令用来声明变量,它的用法类似于var,但是所声明的变量只在let命令所在的代码块内生效. 所以在for循环中,就很适合使用let命令. 上面 ...
 - SpringAOP(5)
			
2019-03-08/14:22:58 演示:登陆核心业务类与日志周边功能实现AOP面向切面思想 jar包:https://share.weiyun.com/5GOFouP 学习资料:http://h ...
 - Mybatis学习---连接MySQL数据库
			
[目录]
 - Docker 使用 Dockerfile 构建自己的镜像
			
可以使用Dockerfile的配置文件方式进行构建自己的镜像 下面利用docker构建一个Caddy web服务器 构建脚本 Dockerfile有自己的命令,下面使用了一些比较常用的命令,更多的Do ...
 - Java中字符串相加和字符串常量相加区别
			
有一道这样的程序: public class TestStringDemo { public static void main(String[] args) { String s1 = "P ...
 - Spark 基本函数学习笔记一
			
Spark 基本函数学习笔记一¶ spark的函数主要分两类,Transformations和Actions. Transformations为一些数据转换类函数,actions为一些行动类函数: ...