kubernetes官方提供了中文文档,网上也有不少中文教程,可是实际的安装过程中,还是遇到了不少的坑。主要有:
- kubernetes的版本迭代比较迅速。网上教程中版本多是
1.6
这样的,最新的k8s版本是1.13.0
- kubernetes的需要安装的rpm包及docker镜像国内直接安装会失败。
- 官方的中文文档在翻译不全,其中一些内容缺失。
发文时kubernetes1.14.0已经正式发布,稍后会奉上更新手册, 敬请期待。
我花了一些时间踩坑,主要参考kubernetes官网、github及stack overflow, 成功完成k8s的安装,过程记录如下。
机器准备
我们在内网的2台服务器上开始k8s的安装,机器配置及规划如下表:
机器名称 | 机器IP | CPU | 内存 | Linux版本 | Docker版本 | 用途 |
192-168-10-21 | 192.168.10.21 | 8 | 16G | CentOS 7.1.1503 | 17.03.2-ce/17.03.2-ce | master控制节点 |
192-168-10-18 | 192.168.10.18 | 8 | 28G | CentOS 7.6.1810 | 17.03.1-ce/17.03.1-ce | worker业务节点 |
Docker版本为:Client Version/Server Version的格式
本次安装的k8s版本是 v1.13.0
,另外实测CentOS的小版本和Docker的小版本不用完全一致。
安装环境准备及安装
安装k8s设备环境要求主要有下面10点:
1. CentOS版本为7以上 2. 2核CPU和2G内存以上 3. 多台机器内网互通 4. 每台机器的主机名、mac地址和product_uuid唯一 5. 测试环境关闭防火墙,保证全部端口开放。 6. 禁用SELinux 7. 禁用交换分区 8. docker服务 9. root账号权限 10. 配置国内的repo源
- 查看机器CentOS版本
[root@192-168-10-21 ~]# cat /etc/centos-release CentOS Linux release 7.1.1503 (Core)
注意CentOS6升级到7比较麻烦,本着少折腾原则,从CentOS7的机器开始会省事一些。
- 查看机器的cpu和内存信息
比较简单和常用的可以使用TOP
命令后再按1
查看:
TOP 1 Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie %Cpu0 : 2.0 us, 1.0 sy, 0.0 ni, 97.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 1.0 us, 0.3 sy, 0.0 ni, 98.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.7 us, 0.7 sy, 0.0 ni, 98.3 id, 0.3 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 0.7 us, 0.3 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu5 : 1.3 us, 0.7 sy, 0.0 ni, 98.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu6 : 0.7 us, 0.7 sy, 0.0 ni, 98.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu7 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 16207100 total, 13269888 free, 974208 used, 1963004 buff/cache
上面信息可知,机器是8核,内存是16G。
更准确的查看CPU信息:
# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c 8 Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz
查看内存信息:
# cat /proc/meminfo | grep MemTotal MemTotal: 16207100 kB 0 0 0
- 多台机器互通,这一般没有问题,不用介绍。
- 检查机器名称、mac及product_uuid的唯一性
# 查看uuid # cat /sys/class/dmi/id/product_uuid 564D0DF3-FB05-2EC7-E989-FFE0F880069C # 查看hostname # hostname 192-168-10-21 # 查看IP # ifconfig -a ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.10.21 netmask 255.255.255.0 broadcast 192.168.10.255 inet6 fe80::20c:29ff:fe80:69c prefixlen 64 scopeid 0x20<link> ether 00:0c:29:80:06:9c txqueuelen 1000 (Ethernet) RX packets 5333851 bytes 529922710 (505.3 MiB) RX errors 0 dropped 152075 overruns 0 frame 0 TX packets 2560325 bytes 916120110 (873.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
一般来说uuid和mac不可能重复,hostname可能会有重复(因为运维开机器是脚本批处理,可能没有修改hostname)。如果hostname重复,修改的方法如下:
1 vi /etc/hostname 修改名称。2 vi /etc/hosts 增加机器名称。 3 roboot重启机器。
- 关闭防火墙
k8s对master和worker节点的端口开放有要求:
因为是内网测试服务,我简单粗暴的关闭防火墙即可。
查看firewall状态:
# systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: inactive (dead)
查看iptables状态:
# systemctl status iptables ● iptables.service - IPv4 firewall with iptables Loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled) Active: inactive (dead)
关闭防火墙
systemctl stop firewalld
停止防护墙开机启动systemctl disable firewalld
。iptables的关闭同理。
- 禁用SELinux
禁用SELinux后,容器才能够访问宿主机文件系统。查看SELinux的状态:
# sestatus SELinux status: disabled
禁用方法
setenforce 0 && sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
- 禁用交换分区
查看交换分区状态,如果swap数值全部为0,则表示已经禁用。
[root@192-168-10-21 ~]# free -h total used free shared buff/cache available Mem: 15G 940M 13G 17M 1.4G 14G Swap: 0B 0B 0B
禁用方法如下
1. run swapoff -a : this will immediately disable swap. 2. remove any swap entry from /etc/fstab. 3. reboot.
- docker服务
查看docker版本:
[root@192-168-10-18 ~]# docker version Client: Version: 17.03.1-ce API version: 1.27 Go version: go1.7.5 Git commit: c6d412e Built: Mon Mar 27 17:05:44 2017 OS/Arch: linux/amd64 Server: Version: 17.03.1-ce API version: 1.27 (minimum version 1.12) Go version: go1.7.5 Git commit: c6d412e Built: Mon Mar 27 17:05:44 2017 OS/Arch: linux/amd64 Experimental: false
- root账号
安装 kubeadm
时候需要使用root账号进行安装。安装完成后推荐非root账号使用 kubectl
命令。
- 配置国内的repo源
kubeadm
使用yum
命令进行安装,使用国内阿里云的源,可以安装成功
cat >> /etc/yum.repos.d/kubernetes.repo <<EOF [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
- 修改网络配置
cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF
修改完成后执行sysctl --system
应用。
- 安装kubernetes包
安装条件全部具备以后, root
账号进入 192-168-10-21
,执行下面命令:
[root@192-168-10-21 ~]# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
完成后启动kubelet
服务
systemctl enable kubelet.service systemctl start kubelet.service
以上12项操作需要在所有节点执行。
初始化k8s集群
1.1 初始化集群
master上使用下面命令初始化k8s:
kubeadm init --kubernetes-version v1.13.0 --pod-network-cidr=10.244.0.0/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.10.21:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:564e3ba4b76649e981300fcea9e4400b759f91a02f4a968e035ada454f3a1d2e
这段提示主要介绍了3点:
1. 推荐非root账号使用`kubectl`命令。本文使用hall账号。 2. 需要在集群中创建pod network。本文使用flannel, 初始化命令中的`--pod-network-cidr=10.244.0.0/16`是使用flannel的必备参数,详情见官方英文文档。 3. 显示了其它节点加入集群的命令。
查看kubectl的版本信息:
$ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T21:04:45Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T20:56:12Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"linux/amd64"}
查看节点:
[hall@192-168-10-21 ~]$ kubectl get nodes NAME STATUS ROLES AGE VERSION 192-168-10-21 NotReady master 41m v1.13.0
这里master的状态为NotReady是因为还没有进行pod network安装。
1.2 使用阿里云的docker hub镜像
如果网络ok,使用1.1的方法安装不会存在问题。但是国内可能一些镜像无法下载,可以使用阿里云的docker hub镜像进行安装。
首先输出kubeadm
默认配置:
kubeadm config print init-defaults > kubeadm-init.yaml
配置内容大概如下:
apiVersion: kubeadm.k8s.io/v1beta1 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 1.2.3.4 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: 192-168-10-21 taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta1 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controlPlaneEndpoint: "" controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.13.0 networking: dnsDomain: cluster.local podSubnet: "" serviceSubnet: 10.244.0.0/16 scheduler: {}
注意:
- imageRepository修改成 registry.cn-hangzhou.aliyuncs.com/google_containers
- serviceSubnet部分设置成10.244.0.0/16,也就是--pod-network-cidr=10.244.0.0/16参数。
然后先进行镜像下载:
kubeadm config images pull --config kubeadm-init.yaml
最后再使用修改后的配置进行初始化:
kubeadm init --config kubeadm-init.yaml
也可以通过在每个节点得docker daemon.json 中配置镜像方式提速下载。
- work节点加入
在work节点上执行kubeadm init完成后得到的join命令:
[root@192-168-10-18 ~]#kubeadm join 192.168.10.21:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:564e3ba4b76649e981300fcea9e4400b759f91a02f4a968e035ada454f3a1d2e
再次在master上查看节点:
[hall@192-168-10-21 ~]$ kubectl get nodes NAME STATUS ROLES AGE VERSION 192-168-10-18 NotReady <none> 98s v1.13.0 192-168-10-21 NotReady master 41m v1.13.0
可以看到work节点192-168-10-18已经正常加入k8s集群了。
- 后期work节点加入
如果join命令丢失或者过期,可以在master上执行下面命令,生成一个token:
[root@192-168-10-21 ~]# kubeadm token generate ffppwv.04qrmsdwm6netaaq
然后使用刚生成得token得到加入命令:
[root@192-168-10-21 ~]# kubeadm token create ffppwv.04qrmsdwm6netaaq --print-join-command --ttl=24h kubeadm join 192.168.10.21:6443 --token pnstpk.kk3aevbn6i5mlsok --discovery-token-ca-cert-hash sha256:5ae89f1949e60f824b129c5520dc05f6da97cb8fa3edb806c3abb38eb439e007
- --ttl=24h 代表这个Token 的有效期为 24 小时,初始化默认生成的 token 有效期也为 24 小时
- join的语法是:
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>
然后work节点使用这个命令加入集群。
- 安装flannel网络
安装flannel网络很简单,分下面2步:
先下载yml文件:
curl -O https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
然后创建flannel:
kubectl create -f kube-flannel.yml
完成后可以检查:
[hall@192-168-10-21 ~]$ kubectl get nodes NAME STATUS ROLES AGE VERSION 192-168-10-18 Ready <none> 102d v1.13.0 192-168-10-21 Ready master 102d v1.13.0
这时候节点的状态应该是Ready。同时也可以查看flannel的pod:
[tyhall51@192-168-10-21 ~]$ kubectl get pods -n kube-system | grep flannel kube-flannel-ds-amd64-j7lxz 1/1 Running 1 102d kube-flannel-ds-amd64-lzjxg 1/1 Running 10 102d 复制代码
- 删除节点
删除节点可以使用:
kubeclt delete node 192-168-10-18
Dashboard安装
k8s完成后,可以使用 kubectl
进行所有控制。官方还提供了dashboard这种web界面,方便管理,一样分2步。
先下载配置:
curl -o kubernetes-dashboard.yaml https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml curl -o heapster.yaml https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/influxdb.yaml curl -o heapster-rbac.yaml https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/rbac/heapster-rbac.yaml curl -o influxdb.yaml https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/influxdb.yaml
然后创建:
kubectl create -f kubernetes-dashboard.yaml kubectl create -f heapster.yaml kubectl create -f heapster-rbac.yaml kubectl create -f influxdb.yaml
也可以使用kubectl create -f .
一键将目录下所有的yaml配置到k8s。
使用命令修改服务类型:
kubectl -n kube-system edit service kubernetes-dashboard
修改 type: ClusterIP 成 type: NodePort 保存。 (kubectl edit 和vi一样操作)
测试服务使用NodePort暴露到集群外,方便访问
然后查看dashboard暴露出来的本地端口:
[hall@192-168-10-21 dashboard]$ kubectl -n kube-system get service kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes-dashboard NodePort 10.96.228.185 <none> 443:32145/TCP 6d21
熟悉docker的就会知道,这里显示了dashboard容器的443端口映射到本地32145端口,然后我们使用https://192.168.10.21:32145
访问.
访问需要token登录,下面是获取token的命令:
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')
效果如下:
增加Master节点
完成之前的内容,已经有一个初具规模的k8s集群了。如果要比较正式的集群,结合etcd的特性,控制节点多备,至少需要3台master节点。接下来继续介绍一下如何添加master节点。
使用命令 kubectl -n kube-system edit cm kubeadm-config
修改controlPlaneEndpoint值为192.168.10.21:6443,然后确认信息修改完成:
[hall@192-168-10-21 ~]$ kubectl -n kube-system get cm kubeadm-config -oyaml apiVersion: v1 data: ClusterConfiguration: | apiServer: extraArgs: authorization-mode: Node,RBAC timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta1 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controlPlaneEndpoint: "192.168.10.21:6443" controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.13.0 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 scheduler: {} ClusterStatus: | apiEndpoints: 192-168-10-21: advertiseAddress: 192.168.10.21 bindPort: 6443 apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterStatus kind: ConfigMap metadata: creationTimestamp: "2018-12-14T03:12:12Z" name: kubeadm-config namespace: kube-system resourceVersion: "13566522" selfLink: /api/v1/namespaces/kube-system/configmaps/kubeadm-config uid: 0cf52c5b-ff4e-11e8-af11-000c2980069c
这个ConfigMap就是之前kubeadm得config文件。
复制第一个master节点上的相关证书到需要添加为master的192-168-10-14节点上,证书清单如下:
/etc/kubernetes/pki/sa.key /etc/kubernetes/pki/sa.pub /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/ca.key /etc/kubernetes/pki/front-proxy-ca.crt /etc/kubernetes/pki/front-proxy-ca.key /etc/kubernetes/pki/etcd/ca.crt /etc/kubernetes/pki/etcd/ca.key /etc/kubernetes/admin.conf
然后在192-168-10-14上执行join命令,等待命令执行完成。
kubeadm join 192.168.10.21:6443 --token ffppwv.04qrmsdwm6netaaq --discovery-token-ca-cert-hash sha256:0cd1dcabee49dd12aaf7913eab9b0fc0e5bda2be9c35f17ce0c0864c7a5bbdb1 --experimental-control-plane
这个过程可能需要几分钟,期间kubectl会失效,耐心等待一下。
注意: 比添加work节点多了 --experimental-control-plane 参数
在第一个master节点执行 kubectl label nodes 192-168-10-14 node-role.kubernetes.io/master=""
,标记 192-168-10-14 为master
检查一下节点情况:
[hall@192-168-10-21 ~]$ kubectl get nodes NAME STATUS ROLES AGE VERSION 192-168-10-14 Ready master 17m v1.13.1 192-168-10-18 Ready <none> 102d v1.13.0 192-168-10-21 Ready master 102d v1.13.0
最后给 192-168-10-14 增加一个污点,标记为业务不可调度
kubectl taint nodes 192-168-10-14 node-role.kubernetes.io/master="":NoSchedule
这样就完成了master节点的添加,可以重复步骤添加第3个master节点。如果是正式服务,要完成高可用,还需用HA代理3个master节点的6443端口。其实现过程主要就是HA的配置,这里就不在详细介绍了。
自此,一个测试用的k8s集群就搭建完成。简单总结一下搭建过程:
- 按照官方要求进行环境监测和安装kubelet、kubeadm、kubectl三个包。
- Master上初始化启动k8s集群,将节点加入集群和配置集群flannel网络。
- 安装dashboard,可视化管理集群。
- 增加master节点,支持高可以。