- 安装 docker.io
如果你用其他 cgroup driver 安装了 docker,需要确保 docker 和 Kubernetes 使用相同的 cgroup driver。
1
2
3
4
5
| cat << EOF >> /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
|
- 向系统添加 apt key 和源
1
2
3
4
5
| root@kube-master:~# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
OK
root@kube-master:~# cat <<EOF >> /etc/apt/sources.list.d/kubernetes.list
> deb http://apt.kubernetes.io/ kubernetes-xenial main
> EOF
|
然后安装 kubernetes 相关包
1
2
| root@kube-master:~# apt update -y
root@kube-master:~# apt install -y kubelet kubeadm kubectl
|
- 使用 kubeadm 进行设置和配置
执行 kubeadm init
时必须选择 CNI,这里选择 flannel,所以要加 --pod-network-cidr
选项。
1
| root@k8sm:~# kubeadm init --pod-network-cidr=10.244.0.0/16
|
等待一会儿后,你会看到如下提示,表示安装完成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 192.168.122.75:6443 --token .....<snip>
|
按照提示,以普通用户执行如下命令:
1
2
3
| mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
还要记下以 kubeadm join
开头的命令,后续让工作节点加入集群时会用到。
为了让 Pod 之间能互相通信,需要安装 Pod 网络插件。这里我们用 Flannel。
1
| kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
|
接下来运行如下命令,确保一切正常启动。
1
| kubectl get pods --all-namespaces
|
如果看到 coredns-xxxxxx pod 处于 Running 状态,master 节点为 Ready,说明集群已准备好接受工作节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
| wshi@k8sm:~$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcdf6894-ltgw2 1/1 Running 0 17m
kube-system coredns-78fcdf6894-n8hw2 1/1 Running 0 17m
kube-system etcd-k8sm 1/1 Running 0 16m
kube-system kube-apiserver-k8sm 1/1 Running 0 16m
kube-system kube-controller-manager-k8sm 1/1 Running 0 16m
kube-system kube-flannel-ds-amd64-ktcqm 1/1 Running 0 1m
kube-system kube-proxy-nczhf 1/1 Running 0 17m
kube-system kube-scheduler-k8sm 1/1 Running 0 16m
wshi@k8sm:~$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8sm Ready master 17m v1.11.2
|
- 设置其他节点并加入集群
剩下的工作节点同样安装 kubectl、kubeadm、kubelet、docker,然后执行前面记下的 kubeadm join ...
命令。
稍等片刻,所有工作节点都应为 Ready。
1
2
3
4
5
| wshi@k8sm:~$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8sm Ready master 44m v1.11.2
k8sn1 Ready <none> 11m v1.11.2
k8sn2 Ready <none> 11m v1.11.2
|
运行 Job#
Pod 内运行的应用称为"Job"。
大多数 Kubernetes 对象都是用 yaml 创建的。下面是一个用 perl 计算圆周率到 2000 位的小 Job 示例 yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
|
在 master 节点上保存为 “pi-job.yaml”,用如下命令运行:
1
| kubectl create -f pi-job.yaml
|
用如下命令查看 Job 详情:
1
2
3
4
5
6
| $ kubectl get pod
...
pi-72c7r 0/1 Completed 0 3m
$ kubectl describe pod pi-72c7r
...
|
用如下命令查看日志(标准输出):
1
2
| $ kubectl logs pi-72c7r
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275898
|
另一个 Job 示例#
下面是一个使用 “busybox” 镜像并 sleep 10 秒的 Job 示例 yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: batch/v1
kind: Job
metadata:
name: busybox
spec:
template:
spec:
containers:
- name: busybox
image: busybox
command: ["sleep", "10"]
restartPolicy: Never
backoffLimit: 4
|
部署 Pod#
Pod 通常代表 Kubernetes 集群中运行的应用。以下是一个定义 Pod 的 yaml 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: default
spec:
containers:
- name: alpine
image: alpine
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
|
运行 Pod#
1
| kubectl create -f alpine.yaml
|
删除 Pod#
1
| kubectl delete -f alpine.yaml
|
或者
1
| kubectl delete pod alpine
|
1
| kubectl delete pod/alpine
|
查看当前状态#
1
2
3
| kubectl get nodes
kubectl describe node node-name
kubectl get pods --all-namespaces -o wide
|
使用 -n
可以指定 namespace
1
| kubectl get pods -n kube-system
|
Deployment#
nginx 部署的 yaml 文件示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
|
创建 deployment 和 pod#
1
| kubectl create -f nginx-deployment.yaml
|
查看详细信息
1
| kubectl describe deployment nginx-deployment
|
查看 pod 运行在哪个节点
1
2
3
| $ kubectl get pod nginx-deployment-7fc9b7bd96-c6wwh -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-deployment-7fc9b7bd96-c6wwh 1/1 Running 0 21h 10.1.33.6 juju-cfb27c-2 <none>
|
滚动升级镜像版本#
将镜像版本改为 1.8,可以运行:
1
| kubectl set image deployment nginx-deployment nginx=nginx:1.8
|
或者直接修改 yaml 文件中的镜像版本为 1.8,然后 apply
1
| kubectl apply -f nginx-deployment.yaml
|
查看滚动升级状态
1
| kubectl rollout status deployment nginx-deployment
|
回滚到上一个版本
1
| kubectl rollout undo deployment nginx-deployment
|
查看历史记录
1
| kubectl rollout history deployment nginx-deployment
|
回滚到指定 revision
1
| kubectl rollout history deployment nginx-deployment --revision=x
|
设置容器环境变量#
部署一个打印环境变量的 Pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| apiVersion: v1
kind: Pod
metadata:
name: env-dump
spec:
containers:
- name: busybox
image: busybox
command:
- env
env:
- name: STUDENT_NAME
value: "Your Name"
- name: SCHOOL
value: "Linux Academy"
- name: KUBERNETES
value: "is awesome"
|
Pod 执行后,可以通过日志查看环境变量
1
2
3
4
5
6
| $ kubectl logs env-dump
....
STUDENT_NAME=Your Name
SCHOOL=Linux Academy
KUBERNETES=is awesome
....
|
Pod 扩容#
命令行方式#
用 –replicas=X 扩容 deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| $ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 2 2 2 2 21h
$ kubectl scale deployment nginx-deployment --replicas=3
deployment.extensions/nginx-deployment scaled
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 21h
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
...
nginx-deployment-7fc9b7bd96-c6wwh 1/1 Running 0 21h
nginx-deployment-7fc9b7bd96-kddj5 1/1 Running 0 31s
nginx-deployment-7fc9b7bd96-s86gc 1/1 Running 0 21h
|
yaml 文件方式#
修改 yaml 文件中的 replicas: x
,然后 apply
1
| kubectl apply -f nginx-deployment.yml
|
Replication Controller、ReplicaSet 和 Deployment#
Deployment 替代了旧的 ReplicationController 功能,但了解原理也很有用。
ReplicationController 保证任意时刻有指定数量的 pod 副本在运行。
以 nginx 容器为例,保持 3 个副本:
Replication Controller#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 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
|
ReplicaSet#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
|
Deployment#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| apiVersion: apps/v1beta2 # 1.8.0 之前用 apps/v1beta1
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
ports:
- containerPort: 80
|
Label#
给节点打颜色标签
1
2
3
4
| kubectl label node node1-name color=black
kubectl label node node2-name color=red
kubectl label node node3-name color=green
kubectl label node node4-name color=blue
|
给 default namespace 下所有 pod 打标签
1
| kubectl label pods -n default color=white --all
|
按标签获取 pod/node 等
1
| kubectl get pods -l color=white -n default
|
多标签筛选
1
| kubectl get pods -l color=white,app=nginx
|
DaemonSet#
在所有节点上部署 nginx pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| apiVersion: apps/v1
kind: DaemonSet
metadata:
name: cthulu
labels:
daemon: "yup"
spec:
selector:
matchLabels:
daemon: "pod"
template:
metadata:
labels:
daemon: pod
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: cthulu-jr
image: nginx
|
确认每个节点上 pod 是否运行
1
2
3
4
5
| $ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
cthulu-kvbk9 1/1 Running 0 2m 10.1.33.8 juju-cfb27c-2 <none>
cthulu-t7hfc 1/1 Running 0 2m 10.1.45.13 juju-cfb27c-1 <none>
cthulu-x8hdf 1/1 Running 0 2m 10.1.31.9 juju-cfb27c-3 <none>
|
给节点打标签并调度 Pod#
给节点打标签
1
| kubectl label node juju-cfb27c-3 deploy=here
|
yaml 文件中用 nodeSelector
指定 pod 部署到特定节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- name: busybox
image: busybox
command:
- sleep
- "300"
imagePullPolicy: IfNotPresent
restartPolicy: Always
nodeSelector:
deploy: here
|
确认
1
2
3
| $ kubectl get pod busybox -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
busybox 1/1 Running 0 10s 10.1.31.10 juju-cfb27c-3 <none>
|
指定调度器#
通常不需要在 spec 里指定 schedulerName,但如果要用自定义调度器可以这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: v1
kind: Pod
metadata:
name: annotation-default-scheduler
labels:
name: multischeduler
annotations:
scheduledBy: custom-scheduler
spec:
schedulerName: custom-scheduler
containers:
- name: pod-container
image: k8s.gcr.io/pause:2.0
|
查看 pod 当前日志
实时查看日志
1
| kubectl logs pod-name -f
|
只看最后 10 行
1
| kubectl logs pod-name --tail=10
|
主机/节点上的日志文件在 /var/log/containers
目录下
节点维护#
维护节点时,可以阻止调度新 pod 并驱逐现有 pod(DaemonSet 除外)。
例如将 juju-cfb27c-2 从集群中移除:
1
2
3
| root@juju-cfb27c-0:~# kubectl drain juju-cfb27c-2 --ignore-daemonsets
node/juju-cfb27c-2 cordoned
WARNING: Ignoring DaemonSet-managed pods: cthulu-kvbk9, nginx-ingress-kubernetes-worker-controller-t6qh9
|
juju-cfb27c-2 状态变为 “SchedulingDisabled”
1
2
3
4
5
| $ kubectl get node
NAME STATUS ROLES AGE VERSION
juju-cfb27c-1 Ready <none> 4d v1.11.2
juju-cfb27c-2 Ready,SchedulingDisabled <none> 4d v1.11.2
juju-cfb27c-3 Ready <none> 4d v1.11.2
|
此时可以安全关机维护该节点,新 pod 只会调度到其他节点。
维护完成后恢复节点:
1
2
3
4
5
6
7
| $ kubectl uncordon juju-cfb27c-2
node/juju-cfb27c-2 uncordoned
$ kubectl get node
NAME STATUS ROLES AGE VERSION
juju-cfb27c-1 Ready <none> 4d v1.11.2
juju-cfb27c-2 Ready <none> 4d v1.11.2
juju-cfb27c-3 Ready <none> 4d v1.11.2
|
升级 Kubernetes 组件#
查看当前版本
- 在 master 节点升级 kubeadm
1
| sudo apt upgrade kubeadm
|
查看 kubeadm 版本
- 查看升级计划
1
| sudo kubeadm upgrade plan
|
- 应用升级计划
1
| sudo kubeadm upgrade apply v1.x.x
|
- 升级 kubelet
升级前先 drain 目标节点
1
| kubectl drain NODENAME --ignore-daemonsets
|
手动升级 kubelet
1
2
| sudo apt update
sudo apt upgrade kubelet
|
升级后记得恢复节点
1
| kubectl uncordon NODENAME
|
入站 Node Port 需求#
- Master 节点
- TCP 6443 – Kubernetes API Server
- TCP 2379-2380 – etcd server client API
- TCP 10250 – Kubelet API
- TCP 10251 – Kube-scheduler
- TCP 10252 – kube-controller-manager
- TCP 10255 – Read-only Kubelet API
- Worker 节点
- TCP 10250 – Kubelet API
- TCP 10255 – Read-only Kubelet API
- TCP 30000-32767 – Node Port Services
将 Pod 暴露到互联网#
1
| kubectl expost deployment NAME --type="NodePort" --port XX
|
部署负载均衡器#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Kind:Service
apiVersion: v1
metadata:
name: la-lb-service
spec:
selector:
app: la-lb
ports:
- protocol: TCP
port: 80
targetPort:9376
clusterIP: 10.0.171.223
loadBalancerIP: 78.12.23.17
type: LoadBalancer
|