kubernetes 一些基本的概念

k8s 原理

 

kubernetes API server 作为集群的核心,负责集群各功能之间的通信, 集群内的各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据的时候

通过API Server 提供的 REST 接口(get put post watch) 来实现。

 

场景一: node节点的 kubelet --------> apiserver

node上的 kubelet 进程每隔一个时间周期,就会调用一次API Server接口报告自身状态,API Server接受这些信息后,将节点状态更新到etcd中

kubelet也通过API Server的 WATCH接口监听pod信息,如果监控到新的pod副本被调度绑定到本节点,则执行pod对应的容器的创建和启动,如果

如果监听到pod对象被删除,则删除本节点对应的pod容器。

 

场景二: master kube-controller-manager  --------> apiserver

kube-controller-manager 中的node controller 模块通过 API Server提供的Watch接口,实时监控node的状态信息

controller-manager 作为集群内部的管理控制中心,负责集群内的node,pod副本, 命名空间namespace, 服务账号,资源定额等的管理,当某个node 宕机,

controller manager 就会及时防线故障并自动修复。

 

 

 

 

k8s网络

使用weave网络

 

 

 

 

 

 

 

 

 

 

 

 

etcd 中注册的对象内容。

[root@docker1 ~]# etcdctl ls /registry /registry/controllers /registry/daemonsets /registry/namespaces /registry/ranges /registry/replicasets /registry/serviceaccounts /registry/ingress /registry/clusterrolebindings /registry/secrets /registry/services /registry/certificatesigningrequests /registry/configmaps /registry/clusterroles /registry/deployments /registry/events /registry/minions /registry/pods

 

 

API server: 提供了HTTP Rest接口,可以对所有资源进行增 删 改 查,是整个集群的入口
controller Mananter: 所有资源对象的自动化控制中心

scheduler: 负责资源调度。

kubelet,负责pod的创建 启停,与master 节点密切协作,实现集群管理的功能
kube-proxy: 实现service的通信与负载均衡机制

 

 

DaemonSet

DaemonSet能够让所有(或者一些特定)的Node节点运行同一个pod。当节点加入到kubernetes集群中,pod会被(DaemonSet)调度到该节点上运行,当节点从kubernetes集群中被移除,被(DaemonSet)调度的pod会被移除,如果删除DaemonSet,所有跟这个DaemonSet相关的pods都会被删除。

在使用kubernetes来运行应用时,很多时候我们需要在一个区域(zone)或者所有Node上运行同一个守护进程(pod),例如如下场景:

  • 每个Node上运行一个分布式存储的守护进程,例如glusterd,ceph
  • 运行日志采集器在每个Node上,例如fluentd,logstash
  • 运行监控的采集端在每个Node,例如prometheus node exporter,collectd等

在简单的情况下,一个DaemonSet可以覆盖所有的Node,来实现Only-One-Pod-Per-Node这种情形;在有的情况下,我们对不同的计算几点进行着色,或者把kubernetes的集群节点分为多个zone,DaemonSet也可以在每个zone上实现Only-One-Pod-Per-Node。

 

什么是Deployment

Kubernetes Deployment提供了官方的用于更新Pod和Replica Set(下一代的Replication Controller)的方法,您可以在Deployment对象中只描述您所期望的理想状态(预期的运行状态),Deployment控制器为您将现在的实际状态转换成您期望的状态,例如,您想将所有的webapp:v1.0.9升级成webapp:v1.1.0,您只需创建一个Deployment,Kubernetes会按照Deployment自动进行升级。现在,您可以通过Deployment来创建新的资源(pod,rs,rc),替换已经存在的资源等。

Deployment集成了上线部署、滚动升级、创建副本、暂停上线任务,恢复上线任务,回滚到以前某一版本(成功/稳定)的Deployment等功能,在某种程度上,Deployment可以帮我们实现无人值守的上线,大大降低我们的上线过程的复杂沟通、操作风险。



Deployment的使用场景

 下面是Deployment的典型用例:

  • 使用Deployment来启动(上线/部署)一个Pod或者ReplicaSet
  • 检查一个Deployment是否成功执行
  • 更新Deployment来重新创建相应的Pods(例如,需要使用一个新的Image)
  • 如果现有的Deployment不稳定,那么回滚到一个早期的稳定的Deployment版本
  • 暂停或者恢复一个Deployment

 

kind: 定义的对象: Replicationcontroller,  ReplicaSet  Deployment 区别

Replicationcontroller 的升级版是 ReplicaSet , ReplicaSet支持基于集合的 Label selector, 而RC只支持基于等式的 Lable select

Deployment其实就是内部调用 ReplicaSet.

DaemonSet 根据标签指定pod 在那个服务器上运行,需要与nodeselect 公用。

configMap 设置环境变量

 

server定义的selector 与 Deployment 中的 template 的 lables 对应

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: tomcat
        tier: frontend
    spec:
      containers:
      - name: tomcat
        image: docker.cinyi.com:443/tomcat
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-server
spec:
  ports:
  - port: 11111   # cluster IP 的端口
    targetPort: 8080  # container容器的端口
  selector:
    tier: frontend

 

外部系统访问service 问题

kubernetes 中三种IP 包括

1. NodeIP   node节点的IP地址
2. PodIP     pod的IP地址
3. clusterIP   service的IP地址

nodeIP 是kubernetes集群中每个节点的物理网卡的IP地址, client 访问kubernetes集群使用的IP地址

Pod ip地址 是更具创建的网络类型,网桥分配的IP地址,

clusterIP 是一个虚拟的IP, cluster ip 仅作用于kubernetes service 这个对象, 是由kubernetes管理和分配ip地址,源于cluster ip地址池
[root@kubernetes nginx]# vim /etc/kubernetes/apiserver
# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

cluster IP 无法ping通, 因为没有一个 实体网络对象 响应

cluster ip 只能结合 service port 组成一个具体的通信接口,单独的cluster IP不具备tcp/ip通信基础,

如果 pod 对外访问,需要在servcie 中 指定 type 为 NodePort


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  replicas: 3
  template:
    metadata:
    labels:
      app: tomcat
      tier: frontend
spec:
  containers:
  - name: tomcat
    image: docker.cinyi.com:443/tomcat
  ports:
  - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-server
spec:
  type: NodePort
  ports:
  - port: 11111
    targetPort: 8080
    nodePort: 30001
  selector:
    tier: frontend

 

 

root@kubernetes nginx]# kubectl describe service tomcat-server
Name: tomcat-server
Namespace:            default
Labels:              <none>
Selector:             tier=frontend
Type:                NodePort
IP:                10.254.222.139        #cluster IP 的地址
Port:                <unset> 11111/TCP    #cluster IP 的端口
NodePort:             <unset> 30001/TCP     # nodeport 的端口
Endpoints:            10.0.223.3:8080,10.0.224.2:8080,10.0.225.2:8080   #容器的服务端口
Session Affinity:        None
No events.

 

访问node IP + node port ,可以访问页面

 

nodeport 并没有完全解决外部访问service 的问题, 比如负载均衡问题,如果有10 pod 节点, 如果是用谷歌的GCE公有云,那么可以把 service  type=NodePort 修改为 LoadBalancer.

 

 

2 通过设置pod(daemonset) hostNetwork=true, 将pod中所有容器的端口号直接映射到物理机上, 设置hostNetwork=true的时候需要注意,如果不指定hostport,默认hostport 等于containerport, 如果指定了hostPort, 则hostPort 必须等于containerPort的值。

 

 

 

 deployment创建部署

[root@docker ~]# cat  test_deployment.yaml

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-nginx spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: docker.cinyi.com:443/senyint/im-web ports: - containerPort: 80

 

1. 创建
[root@docker ~]# kubectl create -f /root/test_deployment.yaml

2. 查看状态
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
my-nginx           3         0         0            0           1s

DESIRED 期望的副本数
CURRENT 当前副本数
UP-TO-DATA 最新副本数
AVALLABLE 可用副本数

3. 更新部署(镜像升级)
(1)把image镜像从 docker.cinyi.com:443/senyint/nginx 升级到 docker.cinyi.com:443/senyint/im-web
[root@docker ~]# kubectl set image deployment/my-nginx nginx=docker.cinyi.com:443/senyint/im-web

 

(2) 直接使用edit 修改
[root@docker ~]# kubectl edit deployment/my-nginx

4.扩展副本数
[root@docker ~] kubect scale deployment my-nginx --replicas=10

5.api
 /apis/extensions/v1beta1/namespaces/default/deployments/my-nginx

  

 

 ReplicationController创建部署

apiVersion: v1
kind: ReplicationController
metadata:
  name: im-web
  namespace: test
spec:
  replicas: 3
  template:
    metadata:
      labels:
        name: im-web
    spec:
      volumes:
      - name: workdir
        hostPath:
          path: "/data/log/im-web"
      containers:
      - name: im-web
        image: docker.cinyi.com:443/senyint/im-web:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: workdir
          mountPath: /data/tomcat/logs
扩容副本
[root@docker1 ~]#  kubectl  scale rc im-web --namespace=test --replicas=5

滚动升级
[root@docker1 ~]# kubectl rolling-update im-web --image=docker.cinyi.com:443/senyint/im-web:2017-03-21_10_12

api
/api/v1/namespaces/test/replicationcontrollers/im-web

 

 

 

 

kubernetes volume(存储卷)

volume 是pod中能够被多个容器访问的共享目录, volume 定义在pod上,然后被一个pod里的多个容器挂载到具体的文件目录下,其实volume与pod的声明周期相同,与容器的生命周期无关系,

kubernetes 支持多种类型的volume,如:glusterfs  ceph等分布式文件系统

 

1.emptyDir:

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: tomcat-deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: tomcat-deployment spec: replicas: 3 template: metadata: labels: app: tomcat tier: frontend spec: volumes: - name: workdir emptyDir: {} containers: - name: tomcat image: docker.cinyi.com:443/tomcat ports: - containerPort: 80 volumeMounts: - name: workdir mountPath: /opt --- apiVersion: v1 kind: Service metadata: name: tomcat-server spec: type: NodePort ports: - port: 11111 targetPort: 8080 nodePort: 30001 selector: tier: frontend

emptyDir volume是在pod 分配到node是创建的,初始内容为空,并且无需指定宿主机上的对应的目录文件,当pod从node上移除时,emptydir中的数据也会永久被删除,目前emptyDir无法控制介质种类

emptpdir 的一些用途如下:
1. 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保修
2. 长时间任务的中间过程checkpoint 的临时保存目录
3. 一个容器需要从另一个容器中获取数据的目录。
2. hostPath 为在pod上挂载宿主机上的文件或者目录,

volumes:
- name: "storage"
hostPath:
path: "/data"
-------------------

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: tomcat-deployment spec: replicas: 3 template: metadata: labels: app: tomcat tier: frontend spec: volumes: - name: workdir hostPath: path: "/data" containers: - name: tomcat image: docker.cinyi.com:443/tomcat ports: - containerPort: 80 volumeMounts: - name: workdir mountPath: /opt #把宿主机/data目录挂载到容器的/opt目录下 --- apiVersion: v1 kind: Service metadata: name: tomcat-server spec: type: NodePort ports: - port: 11111 targetPort: 8080 nodePort: 30001 selector: tier: frontend

 

3. gcePersistentDisk google云盘

4.awsEasticblockStore 亚马逊云盘

5 nfs, 使用nfs网络文件服务器提供的共享目录存储数据时,需要部署一个nfs server,定义nfs类型volume 如:

        volumeMounts:
        - name: workdir
          nfs:
server: nfs-server
path: "/"

6. 其他类型的volume

iscsi: 使用iscsi存储设备上的目录挂载到pod上。
flock: 使用flocker来管理存储卷
glusterfs: 使用glusterfs分布式文件系统
等等.....

 

Namespace 命名空间


Namespace 在很多情况下用于多租户的资源隔离,Namespace通过将集群内部的资源对象“分配”到不通的Namespace中, 形成逻辑上的分组的不同项目,小组或者 用户组,便于不同的分组在共享使用这个集群的资源的同时还能被分别管理。



kubernetes集群在启动后,会创建一个 default 的 namespace,


[root@kubernetes nginx]# kubectl get namespace
NAME STATUS AGE
default Active 7d
kube-system Active 7d



如果不特别指明namespace,则用户创建的 pod rc service 都将被系统创建到defalut中



#创建fengjian20170221 的命名空间
apiVersion: v1 kind: Namespace metadata: name: fengjian20170221
--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: tomcat-deployment namespace: fengjian20170221 spec: replicas: 3 template: metadata: labels: app: tomcat tier: frontend spec: volumes: - name: workdir hostPath: path: "/data" containers: - name: tomcat image: docker.cinyi.com:443/tomcat ports: - containerPort: 80 volumeMounts: - name: workdir mountPath: /opt --- apiVersion: v1 kind: Service metadata: name: tomcat-server spec: type: NodePort ports: - port: 11111 targetPort: 8080 nodePort: 30001 selector: tier: frontend

[root@kubernetes nginx]# kubectl get namespace
NAME        STATUS      AGE
default       Active      7d
fengjian20170221 Active      2m
kube-system     Active      7d

 

[root@kubernetes nginx]# kubectl get pods --namespace=fengjian20170221
NAME                   READY    STATUS    RESTARTS AGE
tomcat-deployment-2750437860-4no2f 1/1    Running    0      5m
tomcat-deployment-2750437860-mmk4b 1/1    Running    0      5m
tomcat-deployment-2750437860-yb8u2 1/1    Running    0      5m

 

guestbook 示例:

 

3个php, 1个redis主 ,2 个redis从

[root@kubernetes guestbook]# vim redis-master.yaml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis-master
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: redis-master
    spec:
      containers:
      - name: redis-master
        image: docker.cinyi.com:443/kubeguide/redis-master
        ports:
        - containerPort: 6379
        env:
        - name: hostname
          value: fengjian
---
apiVersion: v1
kind: Service
metadata:
  name: redis-master
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis-master

#########################

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis-slave
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: redis-slave
    spec:
      containers:
      - name: redis-slave
        image: docker.cinyi.com:443/kubeguide/guestbook-redis-slave
        ports:
        - containerPort: 6379
        env:
        - name: GET_HOSTS_FROM
          value: env
---
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis-slave


############################

[root@kubernetes guestbook]# vim frontend-php.yaml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend-server
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: frontend-server
    spec:
      containers:
      - name: frontend-server
        image: docker.cinyi.com:443/kubeguide/guestbook-php-frontend
        ports:
        - containerPort: 80
        env:
        - name: GET_HOSTS_FROM
          value: env
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-server
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
  selector:
    app: frontend-server

[root@kubernetes guestbook]# kubectl   create  -f redis-master.yaml -f redis-slave.yaml  -f frontend-php.yaml

[root@kubernetes guestbook]# kubectl  get service

 

 

 访问 nodeIP+端口, 可以访问出程序页面, 


 

Pod 声明周期和重启策略

状态        描述
Pending      API server 已经创建该Pod,但pod 内还有一个或多个容器的镜像还有创建,包括正在下载镜像的过程
Running      pod内的所有容器均已创建,且至少有一个容器处于运行状态,正在启动状态或正在重启状态。
Successed     Pod内所有容器均成功执行退出,且不会重启
Failed       Pod内所有容器均已退出,但至少一个容器退出为失败状态
Unknown      由于某种原因无法获取该pod的状态,可能由于网络问题

 

Pod重启策略(restartpolicy) 应用于pod内的所有容器,并且仅在pod所处的node上由kubelet进行判断和重启操作,

pod 的重启策略包括always、 onfailure 、 Never, 默认为always.

always: 懂容器失效时,有kubulet自动重启该容器
onfailure: 当容器终止运行且退出码不为0,有kubulet 自动重启容器
never: 不论容器运行状态如何,kubelet都不会重启该容器。

 

 

Pod扩容和缩容

在生产环境中,经常会遇到某个服务需要扩容的场景,也可能会遇到由于资源紧张或工作负载降低减少服务实例的场景,可以使用 RC 的 scale机制操作

 

[root@kubernetes guestbook]# kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
frontend-server-3958566729-0fwym   1/1       Running   0          2h
frontend-server-3958566729-dw937   1/1       Running   0          2h
redis-master-1081272834-nyjra      1/1       Running   0          2h
redis-slave-3198086074-0ijyl       1/1       Running   0          2h
redis-slave-3198086074-6vwya       1/1       Running   0          2h
[root@kubernetes guestbook]# kubectl scale deployment frontend-server --replicas=1    #replicas 副本数变成1个
deployment "frontend-server" scaled
[root@kubernetes guestbook]# kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
frontend-server-3958566729-0fwym   1/1       Running   0          2h
redis-master-1081272834-nyjra      1/1       Running   0          2h
redis-slave-3198086074-0ijyl       1/1       Running   0          2h
redis-slave-3198086074-6vwya       1/1       Running   0          2h

 

静态pod

是由kubelet进行管理的,仅存在于特定的node上的pod, 他们不能功过API server进行管理,无法于ReplicationController,Deployment或者DaemonSet关联

kebelet守护进程监控它,并在崩溃时重启它。 静态pod 总是绑定到一个kubulet守护程序上,并且总是运行在同一个节点上。

 

创建静态pod的两种方式, 1. 配置文件 ,2.http

 

(1)、创建一个yaml文件,并且放置到一个文件夹中/etc/kubelet.d/

[root@docker225 kubelet.d]# mkdir /etc/kubelet.d/
[root@docker225 kubelet.d]# cat static-web.yaml

apiVersion: v1 kind: Pod metadata: name:
static-web labels: role: myrole spec: containers: - name: web image: nginx ports: - name: web containerPort: 80 protocol: TCP

(2) 修改 /etc/kubernetes/kubelet 配置文件,最后一行添加 静态pod的yaml文件的路径。
KUBELET_ARGS="--pod-manifest-path=/etc/kubelet.d/"
(3)重启kulelet 服务
systemctl restart kubelet.service

  (4) 删除静态pod, yaml文件去掉后,会自动删除

   mv static-web.yaml     /root/static-web.xml

 

 

configmap

许多应用程序需要通过配置文件,命令行参数和环境变量的组合进行配置。这些配置工件应该与映像内容解耦,以便保持容器化应用程序可移植。ConfigMap API资源提供了使用配置数据注入容器的机制,同时保持容器与Kubernetes无关

应用部署的一个最佳实践是将应用所需的配置信息与程序进行分离,这样可以使得应用程序被更好的复用,通过不同的配置也能实现更灵活的功能,将应用打包为镜像后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入,

在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常负责, kubernetes提供了一种统一的集群配置管理方案

 

configmap 供容器使用的典型方案如下:

1. 生成为容器内的环境变量

2. 设置容器启动命令的启动参数

3. 以volume的形式挂载为容器内部的文件或者目录

4: 注意必须先创建 configMap, 然后pod 才能创建,如果已经创建的pod,升级,环境变量无法找到,

一定要做好提前规划。

生成为容器内的环境变量

[root@kubernetes configmap]# cat cm-appenv.yaml 

apiVersion: v1
kind: ConfigMap
metadata:
  name: testenv
  namespace: test
data:
  mysql_server: 192.168.20.131
  redis_server: 192.168.20.116
  mongo_server: 192.168.20.116

 
支持所有的kind类型:如下: china.yaml

apiVersion: v1
kind: Service
metadata:
  name: china
  labels:
    app: china
spec:
  ports:
  - port: 80
  selector:
    app: china
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: china
  namespace: test
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: china
    spec:
      containers:
      - name: china
        image: docker.cinyi.com:443/senyint/im-web
        ports:
        - containerPort: 80
        env:
        - name: mysql_server
          valueFrom:
            configMapKeyRef:
              name: testenv
              key: mysql_server
        - name: redis_server
          valueFrom:
            configMapKeyRef:
              name: testenv
              key: redis_server
        - name: mongo_server
          valueFrom:
            configMapKeyRef:
              name: testenv
              key: mongo_server



[root@kubernetes configmap]# kubectl  create -f cm-appenv.yaml -f china.yaml

[root@kubernetes configmap]# kubectl  get pods --all-namespaces -o wide

登陆到pod中,查看env环境变量

  [root@kubernetes configmap]# kubectl exec -it china-3221241881-rlr8w --namespace=test bash

  [root@china-3221241881-rlr8w /]# env | grep -i server

  

  redis_server=192.168.20.116
  mysql_server=192.168.20.131
  mongo_server=192.168.20.116
  mysql-server=192.168.20.131

 

configmap使用 volumeMount模式

 

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
---

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: docker.cinyi.com:443/busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

 

 

DNS服务

为了能够通过服务的名字在集群内部进行服务的相互访问,需要创建一个虚拟的dns服务来完成服务名到clusterIP的解析,

kubernetes 提供的虚拟dns服务器名为skydns,是由4个组件组成
1. etc: dns存储
2. kube2sky: 将kubernetes master 中的service 注册到etcd
3. skydns 提供dns域名解析服务
4. healthz: 提供对skydns服务的健康检查功能

 

创建skydns的yaml文件

apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-dns-v8
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    version: v8
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-dns
    version: v8
  template:
    metadata:
      labels:
        k8s-app: kube-dns
        version: v8
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: etcd
        #image: gcr.io/google_containers/etcd:2.0.9
        image: index.tenxcloud.com/google_containers/etcd:2.0.9
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
        command:
        - /usr/local/bin/etcd
        - -data-dir
        - /var/etcd/data
        - -listen-client-urls
        - http://127.0.0.1:2379,http://127.0.0.1:4001
        - -advertise-client-urls
        - http://127.0.0.1:2379,http://127.0.0.1:4001
        - -initial-cluster-token
        - skydns-etcd
        volumeMounts:
        - name: etcd-storage
          mountPath: /var/etcd/data
      - name: kube2sky
        #image: gcr.io/google_containers/kube2sky:1.11
        image: index.tenxcloud.com/google_containers/kube2sky:1.11
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
        args:
        # command = "/kube2sky"
        - -domain=cinyi.com
        - -kube_master_url=http://192.168.20.226:8080
      - name: skydns
        #image: gcr.io/google_containers/skydns:2015-03-11-001
        image: index.tenxcloud.com/google_containers/skydns:2015-03-11-001
        #image: index.tenxcloud.com/google_containers/skydns:2015-10-13-8c72f8c
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
        args:
        # command = "/skydns"
        - -machines=http://localhost:4001
        - -addr=0.0.0.0:53
        - -domain=cinyi.com
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
      volumes:
      - name: etcd-storage
        emptyDir: {}
      dnsPolicy: Default # Don't use cluster DNS.
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.254.0.2 
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

2. 修改每台node 上的 kubelet启动参数
[root@docker223 ~]# cat /etc/kubernetes/kubelet 
###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=192.168.20.223"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://192.168.20.226:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=docker.cinyi.com:443/rhel7/pod-infrastructure:latest"
#KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

# Add your own!
KUBELET_ARGS="--pod-manifest-path=/etc/kubelet.d/ --cluster_dns=10.254.0.2 --cluster_domain=cinyi.com"

 

 DNS工作原理解析:

1. kube2sky通过调用kubernetes master 的API 获取集群中所有service的信息,并且持续监控新的service 的生成,然后写入etcd中

查看etcd中存储的service 信息

[root@kubernetes nginx]# kubectl exec kube-dns-v8-98n35 -c etcd --namespace=kube-system etcdctl ls /skydns/com/cinyi
/skydns/com/cinyi/default
/skydns/com/cinyi/svc
/skydns/com/cinyi/kube-system

查看tomcat1 服务对应的键值:

[root@kubernetes nginx]# kubectl exec kube-dns-v8-98n35 -c etcd --namespace=kube-system etcdctl get /skydns/com/cinyi/default/tomcat1
{"host":"10.254.100.145","priority":10,"weight":10,"ttl":30,"targetstrip":0}

 

2. kubelet启动参数设置了(--cluster_dns),kubelet会在每个创建的pod中设置dns解析配置 /etc/resolv.conf

[root@docker223 ~]# docker exec -it 2ff /bin/bash
[root@my-nginx-335071150-a8mak nginx-1.11.2]# cat /etc/resolv.conf 
search default.svc.cinyi.com svc.cinyi.com cinyi.com
nameserver 10.254.0.2
nameserver 114.114.114.114
options ndots:5

  

3.应用程序能够通过网站域名进行访问。

[root@my-nginx-335071150-a8mak nginx-1.11.2]# nslookup tomcat1
Server:        10.254.0.2
Address:    10.254.0.2#53

Name:    tomcat1.default.svc.cinyi.com
Address: 10.254.100.145

 

例子:查看所有的service 服务

 

 

进入到 pod容器中后 ping kubernetes-dashboard.kube-system 的server,不同,但是可以解析到IP地址

 

使用telnet kubernetes-dashboard.kube-system  80端口,是通的,

 

结论:service 通过内部IP(虚IP),可以进行通信,但是不能ping通。

 

 

遇到的问题:

1. ingress  如果使用不同namespace,需要使用2个yaml文件

2. 配置一个nginx pod,hostNetwork=true的情况下,进入pod中 dns无法解析到其他services,所以直接采用nginx反向代理service方式行不通。 可以是使用问题6的方式,暴露service的nodePort端口。

3. 容器的hosts: 在dockerfile中,使用add host /etc/,命令,容器启动后,host还是被覆盖

4. 使用configMap,设置环境变量方式,但是一定要提前规划好,当pod已经创建,再修改configmap文件, 添加环境变量 , 启动的pod,环境变量不启用,需要删除pod,重新创建。

5. deployment 与 ReplicationController api不同,升级方法不同

6. DaemoSet类型 实现高可用,需要删除 replicas 参数, 并且设置nodeSelector,只是label, 最后,在node上引用label,kubectl label node docker role=master

7. 所有操作都是用API,与jenkins结合使用。

8. k8s 1.5.3以后 skydns 已经取消, 新的 Kubernetes DNS pod拥有3个容器 kubedns,dnsmasq和一个名为healthz的健康检查。kubedns进程监视Kubernetes主服务和端点的更改,并维护内存中查找结构来服务DNS请求。dnsmasq容器添加DNS缓存以提高性能。healthz容器在执行双重健康检查(对于dnsmasq和kubedns)时提供单个健康检查端点。

 

posted @ 2017-02-21 11:58  fengjian1585  阅读(6237)  评论(2编辑  收藏  举报