k8s 基本使用
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
![](https://images2015.cnblogs.com/blog/886010/201703/886010-20170321100747080-726923512.png)
(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
![](https://images2015.cnblogs.com/blog/886010/201702/886010-20170222145938116-168198979.png)
访问 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
1
2
3
4
5
6
|
[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)时提供单个健康检查端点。