Docker 体验及总结(6) - Kubernetes(待续)
- Master-Node,Master对外提供交互API
- Master:
- API Server:与整个集群交互
- Scheduler:调度模块(如容器创建、所运行的节点)
- Controller:控制模块(负载均衡、横向扩展)
- ETCD:存储集群状态和配置
- Node:
- Pod:调度的最小单位,具有相同Namespace的Container组合
- Docker:容器运行的技术
- Kubelet:负责在Node上创建Container、Volume等
- Kube-proxy:端口代理转发、负载均衡
- Fluentd:日志采集存储查询
- Image Registry
- Optional:DNS,UI...
简介:http://www.imooc.com/article/23476
搭建
先看看Kelsey Hightower大佬的GitHub:https://github.com/kelseyhightower
搭建方法:
- 困难的方法,完全用命令行:https://github.com/kelseyhightower/kubernetes-the-hard-way
- 本地单节点:https://github.com/kubernetes/minikube
- 本地多节点:https://github.com/kubernetes/kubeadm
- 云上多节点:https://github.com/kubernetes/kops(生产级别工具)
- 集群管理工具(10节点以下免费):https://coreos.com/tectonic/
- Play whth Kubernetes(2节点,只能维持4小时): https://labs.play-with-k8s.com/
以通过Minikube搭建集群为例:需要先安装Minikube和kubectl(连接K8S的客户端):https://github.com/kubernetes/minikube
minikube start # 创建一个单节点K8S集群(下载Minikube ISO和localkube binary)
kubectl version
kubectl config view
kubectl config get-contexts # 查看Minikube上下文(每个集群对应一个上下文)
kubectl cluster-info # 查看集群情况
minikube ssh # 连接到minikube的虚拟机,查看docker版本
docker version
使用kubectl自动补全脚本
source <(kubectl completion zsh)>
kubectl completion zsh
Pods
Pods- K8S基本调度单位(K8S不直接对Container操作),包括一或多个Container;
- Pod中的Container共享Namespace(用户、网络、存储),Container中的通信直接通过localhost。
实例:以Nginx为例,创建一个pod
vim pod_nginx.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
kubectl create -f pod_nginx.yml # 指定yml文件创建并启动pod
kubectl delete -f pod_nginx.yml # 删除pod
kubectl get pods # 查看集群中有哪些pod
kubectl get pods -o wide # 查询Pod中的Container信息
操作pod中的container:
方法1:通过docker命令控制
minikube ssh # 先进入minikube虚拟机
docker ps # 查看运行了哪些container
docker exec -it container_id sh
xxx
docker network ls # 查看minikube的bridge
docker network inspect bridge # 查看bridge网络详细信息
方法2:通过K8S命令控制
kubectl exec -it nginx sh # 默认进入Pod中的第一个Container(也可以通过-c选项指定)
kubectl describe nginx pods nginx # 查看某个pod的详细信息
kubectl port-forward nginx 8080:80 # 端口映射(把pod的80端口映射到minikube的8080端口供本地访问,但在终端中保持运行)
kubectl delete -f pod_nginx.yml # 删除pod
ReplicationController
通过ReplicationController创建pod可维持指定数量的副本(Down以后自动创建)
vim rc_nginx.yml
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
kubectl create -f rc_nginx.yml # 创建3副本的Nginx pod
kubectl get rc
kubectl get pods
kubectl delete pods pod_name # 删除其中一个副本(会发现自动恢复一个,维持3个)
kubectl scale rc nginx --replicas=2 # 改为维持2个副本
kubectl get pods -o wide # 查看pod运行在哪些节点
kubectl delete -f rc_nginx.yml
ReplicaSet
新一代的ReplicationController,支持new set-based
selector
vim rs_nginx.yml # 注意配置与ReplicationController不同
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
labels:
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
name: nginx
labels:
tier: frontend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
kubectl create -f rs_nginx.yml
kubectl get rs
kubectl get pods
kubectl scale rs nginx --replicas=2
Deployment
- 提供ReplicaSets和Pods的声明和实现(副本数、服务版本);
- 通过Deployment创建的ReplicaSets和Pods不能直接操作,而需要对Deployment操作。
vim deployment_nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.12.2
ports:
- containerPort: 80
kubectl create -f deployment_nginx.yml
kubectl get deployment -o wide # 列出所有deployment
kubectl get rs
kubectl get pods
# deployment升级
kubectl set image deployment nginx-deployment nginx=nginx:1.13 # 升级deployment版本
kubectl get rs
kubectl get pods
kubectl rollout history deployment nginx-deployment # 查看deployment历史版本
kubectl rollout undo deployment nginx-deployment # 回滚deployment版本
端口映射
kubectl get node -o wide
kubectl delete services nginx-deployment # 删除services
kubectl expose deployment nginx-deployment --type=NodePort # 把deployment的端口暴露到本地
kubectl get svc # 查看deployment的端口映射关系
多节点环境部署
使用CoreOS的Tectonic-Kubernetes的Sandbox部署多节点环境(基于VirtualBox + Vagrant + SandBox,收费,提供免费试用):https://coreos.com/tectonic/
下载文件到本地,创建K8S虚拟化环境:
# https://github.com/yipwinghong/FileRepository/tree/master/kubernetes/tectonic-sandbox-1.7.5-tectonic.1
cd tectonic-sandbox-1.7.5-tectonic.1
vagrant up
多集群管理:使得kubectl兼容minikube和tectonic的context
kubectl config get-clusters
kubectl config get-contexts
kubectl config use-context tectonic # 使用tectonic的context
kubectl get node
接下来的测试都要使用这个多节点环境。
K8S网络
https://kubernetes.io/docs/concepts/cluster-administration/networking/多机通信:通过flannel插件实现Overlay网络,集群中默认所有的pods之间、主机与pods之间都可以ping通:
# 创建两个pods并查看运行情况
kubectl create -f pod_busybox.yml
kubectl create -f pod_nginx.yml
kubectl get pods -o wide
# pods之间可以ping通
kubectl exec -it busybox-pod sh # 进入busybox pod
ip a
ping 10.0.2.51 # 尝试ping通nginx pod
# 主机与pods也可以ping通
vagrant status # 有两台虚拟机w1和c1,假设两个pod都运行在w1,则c1没有pod运行
vagrant ssh c1 # 进入c1
ping 10.0.2.51 # 在c1也可以ping通两个pod
ping 10.0.2.50
网络插件应该满足要求:
- 所有容器可以互相通信,不需要经过NAT;
- 所有节点可以与所有容器互相通信(哪怕不在一个节点上),不需要经过NAT;
- 容器自身ip可供其他(节点、容器)访问。
Service
不建议直接使用和管理Pods(网络):
- 使用ReplicaSet或ReplicationController水平伸缩scale时,Pods可能会被terminated;
- 使用Deployment时,更新Docker Image Version,旧的Pods会被Terminated,然后创建新的Pods。
Services管理:
-
kubectl exposes
命令,会给我们的pod创建一个Service,供外部访问; - Service主要类型:ClusterIP,NodePort,LoadBalancer(需要结合云服务商使用),ExternalName(需要DNS支持);
- 另外也可以使用DNS,但需要DNS的add-on。
ClusterIP
- ClusterIP只能供内部访问,不能在互联网上提供服务;
- 为pods、deployment等创建service时,默认为ClientIP,如需要指定其他,要添加
--type
选项。
接上,使用测试网路时创建的busybox pod和nginx pod
kubectl get pods -o wide # busybox pod和nginx pod(pod的ip会因重启而变化)
kubectl expose pods nginx-pod # 对外提供nginx pod
kubectl get svc # 查看对外提供服务的pod使用的ip(services的ip不会因重启而变化)
vagrant ssh c1
curl 10.3.248.3 # services的ip
使用service的deployment会自动做负载均衡和滚动升级:
kubectl create -f xxx.yml # 创建deployment
kubectl get deployment # 查看deployment名称
kubectl expose deployment service-test # 创建service
kubectl get svc
# 直接编辑deployment的yml,保存退出后暂时中止,过后自动恢复并升级。
kubectl edit deployment service-test
NodePort
- NodePort Service把端口映射到整个Cluster上的每个节点,所以访问任意一个节点都可以请求到服务;
- 可以绑定NodeIP为公网IP(端口有范围限制),则可以对外提供服务;
- 存在问题:当启动一个服务,需要占用所有节点的相同端口,对于端口是一种浪费。
通过yml创建pods再创建service
vim pod_nginx.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
ports:
- name: nginx-port
containerPort: 80
kubectl create -f pod_nginx.yml
kubectl get pods -o wide
kubectl expose pods nginx-pod --type=NodePort # 给pods创建nodeport service
kubectl get svc
kubectl describe node c1.xxx
直接通过yml创建service
vim service_nginx.yml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- port: 8080
nodePort: 8080
targetPort: nginx-port
protocol: TCP
selector:
app: nginx
type: NodePort
kubectl create -f service_nginx.yml
Label
如一个pod(或其他对象)的yml中定义了nodeSelector
参数,可以指定其运行在具备某个Label的节点上:
apiVersion: v1
kind: Pod
metadata:
name: busybox-pod
labels:
app: busybox
spec:
nodeSelector:
hardware: good
containers:
- name: busybox-container
image: busybox
command:
- sleep
- "360000"
以上pod就只允许允许运行在hardware=good
的节点了,没有的话会一直Pending:
kubectl get nodes --show-labels
# 为节点指定Label,稍后pod就会运行在w1节点上
kubectl label node w1 hardware=good