前言
Kubernetes 1.13 在 2018 年 12 初 GA,这是今年的第四次也是最后一次大版本。此版本继续关注 Kubernetes 的稳定性和可扩展性,其中在存储和群集生命周期领域的三个主要功能实现普遍可用(GA);Kubeadm 简化集群管理、容器存储接口(CSI)和 CoreDNS 作为默认 DNS。
我们用最新的版本来学习,通过使用 Kubeadm 来安装 Kubernetes1.13.0。Kubernetes 的网络要求各节点间可以相互通信,而滴滴云的 VPC 环境是天然的支持。(文末有福利)
1. 目标
第一次安装,我们设一个简单的目标:
- 完成 Kubernetes 1.13 最简单的安装
- 可以在集群中部署简单的服务
2. 准备环境
在滴滴云上创建三台 DC2(虚拟机)
其实不用每个 DC2 都申请 EIP,这里为了安装简单,都配置上。(如果部署单机版,则创建一台,其安装区别是单机版安装后,把 master 设置为可以部署应用,下面安装的时候会有提示)
![v2-3ce99b2011cb3424e985eb19683f7387_b.png](https://i-blog.csdnimg.cn/blog_migrate/6c6bfe7f1bdc8b72ba05945a97e592d5.png)
后面的安装均以 root 用户进行操作,切换到 root,在命令行中 root 用户的提示符为 #,普通用户的为 $
[dc2-user@10-254-165-64 ~]$ sudo -i
[root@10-254-165-64 ~]#
默认情况下滴滴云的 DC2 的防火墙是关着的,这里不用再关闭。如果你的环境开着,先关闭。关闭的方式如下:
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config
setenforce 0
3. 安装
添加 Kubernetes yum 源
[root@10-254-11-44 ~]# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
执行 yum 安装
[root@10-254-165-64 ~]# yum install -y docker kubelet kubeadm kubectl kubernetes-cni
安装完成后,可以看见下面安装成功的提示:
已安装:
docker.x86_64 2:1.13.1-53.git774336d.el7.centos kubeadm.x86_64 0:1.13.0-0 kubectl.x86_64 0:1.13.0-0 kubelet.x86_64 0:1.13.0-0
kubernetes-cni.x86_64 0:0.6.0-0
作为依赖被安装:
container-selinux.noarch 2:2.42-1.gitad8f0f7.el7 container-storage-setup.noarch 0:0.8.0-3.git1d27ecf.el7
cri-tools.x86_64 0:1.12.0-0 device-mapper-event.x86_64 7:1.02.140-8.el7
device-mapper-event-libs.x86_64 7:1.02.140-8.el7 device-mapper-persistent-data.x86_64 0:0.7.0-0.1.rc6.el7_4.1
docker-client.x86_64 2:1.13.1-53.git774336d.el7.centos docker-common.x86_64 2:1.13.1-53.git774336d.el7.centos
ebtables.x86_64 0:2.0.10-15.el7 libaio.x86_64 0:0.3.109-13.el7
lvm2.x86_64 7:2.02.171-8.el7 lvm2-libs.x86_64 7:2.02.171-8.el7
oci-register-machine.x86_64 1:0-6.git2b44233.el7 oci-systemd-hook.x86_64 1:0.1.15-2.gitc04483d.el7
oci-umount.x86_64 2:2.3.3-3.gite3c9055.el7 skopeo-containers.x86_64 1:0.1.28-1.git0270e56.el7
socat.x86_64 0:1.7.3.2-2.el7 yajl.x86_64 0:2.0.4-4.el7
完毕!
安装好后检查一下 Docker和 Kubeadm 版本
[root@10-254-11-44 ~]# docker --version
Docker version 1.13.1, build 774336d/1.13.1
[root@10-254-11-44 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T21:02:01Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"linux/amd64"}
启动 Docker 和 Kubelet 服务
[root@10-254-11-44 ~]# systemctl enable docker && systemctl start docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@10-254-11-44 ~]# systemctl enable kubelet && systemctl start kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.
执行 kubeadm config images list
查看安装 Kubernetes 需要哪些依赖
这个操作会卡一会儿,提示 dl.k8s.io
不可达,但是会输出需要的镜像源及对应的版本,这一步可以直接跳过。
[root@10-254-11-44 ~]# kubeadm config images list
...
k8s.gcr.io/kube-apiserver:v1.13.0
k8s.gcr.io/kube-controller-manager:v1.13.0
k8s.gcr.io/kube-scheduler:v1.13.0
k8s.gcr.io/kube-proxy:v1.13.0
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.2.24
k8s.gcr.io/coredns:1.2.6
下载依赖包,国内的网络环境下载依赖包比较困难,笔者已经把对应的包同步到 Docker Hub 上面了
docker pull ww3122000/kube-apiserver:v1.13.0
docker pull ww3122000/kube-controller-manager:v1.13.0
docker pull ww3122000/kube-scheduler:v1.13.0
docker pull ww3122000/kube-proxy:v1.13.0
docker pull ww3122000/pause:3.1
docker pull ww3122000/etcd:3.2.24
docker pull ww3122000/coredns:1.2.6
docker tag ww3122000/kube-apiserver:v1.13.0 k8s.gcr.io/kube-apiserver:v1.13.0
docker tag ww3122000/kube-controller-manager:v1.13.0 k8s.gcr.io/kube-controller-manager:v1.13.0
docker tag ww3122000/kube-scheduler:v1.13.0 k8s.gcr.io/kube-scheduler:v1.13.0
docker tag ww3122000/kube-proxy:v1.13.0 k8s.gcr.io/kube-proxy:v1.13.0
docker tag ww3122000/pause:3.1 k8s.gcr.io/pause:3.1
docker tag ww3122000/etcd:3.2.24 k8s.gcr.io/etcd:3.2.24
docker tag ww3122000/coredns:1.2.6 k8s.gcr.io/coredns:1.2.6
上面的内容在每个节点上面都执行,下面的在 master 上面执行。
初始化集群
这儿带上参数 --kubernetes-version=v1.13.0
是为了防止以后看教程的时候版本更新了,会安装更新的版本,导致安装失败。使用 --pod-network-cidr=172.16.0.0/12
是为了支持 CNI 网络插件。
[root@10-254-11-44 ~]# kubeadm init --pod-network-cidr=172.16.0.0/12 --kubernetes-version=v1.13.0
看见下面的输出,表示初始化成功了, 输出的结果中的 kubeadm join ...
的内容为以后在 Node 节点上面添加到集群中需要执行的命令。
...
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 10.254.11.44:6443 --token iqq37y.cx5jpycw939zpkfn --discovery-token-ca-cert-hash sha256:15b997b2e6e127b453a96a96476cb0d68c89c82c42c0aa80cd1169e5bbd6af2e
初始化成功后执行正面的命令复制配置文件到 root 用户和普通用户的 home 目录下,以便连上集群使用,执行上面提示中的三行语句
[root@10-254-165-64 ~]# mkdir -p $HOME/.kube
[root@10-254-165-64 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@10-254-165-64 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
添加 Weave 网络插件
[root@10-254-165-64 ~]# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
添加成功后提示:
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.extensions/weave-net created
如果是单机版本,则执行下面的命令让 master 可以部署应用
[root@10-254-165-64 ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
如果添加其它节点,则在其它两个 Node 节点上做完 Docker 和 Kubeadm 的安装后 执行添加 Node 命令,添加节点到集群中,下面的内容从上面的 kubeadm init 的结果中查找,然后拷贝运行(切记不要复制教程中的)
[root@10-254-165-64 ~]# kubeadm join 10.254.11.44:6443 --token iqq37y.cx5jpycw939zpkfn --discovery-token-ca-cert-hash sha256:15b997b2e6e127b453a96a96476cb0d68c89c82c42c0aa80cd1169e5bbd6af2e
查看集群中 Node 情况
[root@10-254-11-44 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
10-254-11-44 Ready master 9m55s v1.13.0
10-254-203-71 Ready <none> 4m8s v1.13.0
10-254-56-33 Ready <none> 4m5s v1.13.0
到这一步,集群的安装已经完成,下面写两个脚本验证是否可用。
4. 验证 K8s 集群
下面的操作可以使用普通用户来操作 K8s 集群了,一般操作使用普通用户来操作是一个良好的习惯。
通过 ReplicaSet 配置 Tomcat Web 集群
# web-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: web
spec:
replicas: 2
template:
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: tomcat
ports:
- containerPort: 8080
使用 Kubectl 命令创建 ReplicaSet
[dc2-user@10-254-11-44 helloworld]$ kubectl create -f web-rc.yaml
replicationcontroller/web created
查看我们刚部署的两个 Tomcat 的 pod, 刚开始时 pod 的状态可能为 ContainerCreating,使用命令查看,可以看见是在拉取对应的镜像
[dc2-user@10-254-11-44 helloworld]$ kubectl get pods -l app=web
NAME READY STATUS RESTARTS AGE
web-68s8f 0/1 ContainerCreating 0 43s
web-t9mbh 0/1 ContainerCreating 0 43s
使用命令查看,可以看见是在拉取 Tomcat的镜像:
[dc2-user@10-254-11-44 helloworld]$ kubectl describe pod web-68s8f
Name: web-68s8f
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: 10-254-203-71/10.254.203.71
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 117s default-scheduler Successfully assigned default/web-68s8f to 10-254-203-71
Normal Pulling 116s kubelet, 10-254-203-71 pulling image "tomcat"
过一会儿,拉取完后,可以看见两个 pod 处于运行状态:
[dc2-user@10-254-11-44 helloworld]$ kubectl get pods -l app=web
NAME READY STATUS RESTARTS AGE
web-68s8f 1/1 Running 0 3m42s
web-t9mbh 1/1 Running 0 3m42s
查看 pod 的 IP,并使用 pod IP 对 Tomcat 进行访问
[dc2-user@10-254-11-44 helloworld]$ kubectl get pods -l app=web -o yaml |grep podIP
podIP: 10.44.0.2
podIP: 10.32.0.4
[dc2-user@10-254-11-44 helloworld]$ curl http://10.44.0.2:8080
...
可以看见输出 tomcat 的欢迎界面的 html
目前只能在服务器上通过 podIP 对服务进行访问,但是我们的 Web 服务肯定是需要向外提供服务的。下面通过创建 Service,对外暴露服务:
创建一个 Tomcat 的 Service 对外暴露服务
Service 的配置中 nodePort: 30303 把服务端口映射到物理机, 同时设置 Service 的 type 为 NodePort, spec.selector 中 app: web 与我们之前创建的 web-rc.yaml
中的 label 一样。
# web-svc-out.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 30303
selector:
app: web
创建 Service
[dc2-user@10-254-11-44 helloworld]$ kubectl create -f web-svc-out.yaml
service/web created
查看 Service
[dc2-user@10-254-11-44 helloworld]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web NodePort 10.106.121.43 <none> 8080:30303/TCP 6m28s
访问服务
在集群中可以使用 集群 IP+ 端口 对服务进行访问:
[dc2-user@10-254-11-44 helloworld]$ curl http://10.106.121.43:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/8.5.35</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>
...
在集群外可以通过 DC2 的内/外网 IP 对集群进行访问:
![v2-e6f43f7076f63672f0ab52b184638b6d_b.png](https://i-blog.csdnimg.cn/blog_migrate/652c77dee61b59a6211fdf6ecd4b720b.png)
OK, 小目标完成。
5. 总结
- 在安装填坑的过程中,网络是最大的问题,解决好网络的问题后,其它相对来说都是小问题
- 在使用 Docker Tag 做
k8s.gcr.io
的包的过程中,不小心把 ETCD 的 image 搞错了,导致安装过程总是不成功,使用docker save load
方式导出本机的 image 又可用。所以在安装过程中需要非常仔细 - 多看官网文档
最后,把安装 master 的相关命令,写成了脚本,可以把脚本拷贝到虚机上面默默地看着自动安装:
[root@10-254-165-64 ~]# sh -x init-k8s.sh
本文作者:汪 伟
参考文档:K8s官网