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)時提供單個健康檢查端點。