一、主机环境预设
环境准备
IP | Name | Role | OS |
---|---|---|---|
192.168.6.240 | master01 | docker-ce,kubelet,kubeadm,kubectl | CentOS7.6 |
192.168.6.241 | node1 | docker-ce,kubelet,kubeadm | CentOS7.6 |
192.168.6.242 | node2 | docker-ce,kubelet,kubeadm | CentOS7.6 |
1、测试环境说明
测试使用的Kubernetes集群可由一个master主机及一个以上(建议至少两个)node主机组成,这些主机可以是物理服务器,也可以运行于vmware、virtualbox或kvm等虚拟化平台上的虚拟机,甚至是公有云上的VPS主机。
本测试环境将由master01、node01和node02三个独立的主机组成,它们分别拥有4核心的CPU及4G的内存资源,操作系统环境均为CentOS 7.6 ,域名为98yz.cn。此外,需要预设的系统环境如下:
(1)借助于NTP服务设定各节点时间精确同步;
(2)通过DNS完成各节点的主机名称解析,测试环境主机数量较少时也可以使用hosts文件进行;
(3)关闭各节点的iptables或firewalld服务,并确保它们被禁止随系统引导过程启动;
(4)各节点禁用SELinux;
(5)各节点禁用所有的Swap设备;
(6)若要使用ipvs模型的proxy,各节点还需要载入ipvs相关的各模块;
2、设定时钟同步
若节点可直接访问互联网,直接启动chronyd系统服务,并设定其随系统引导而启动。
~]# systemctl start chronyd.service
~]# systemctl enable chronyd.service
不过,建议用户配置使用本地的的时间服务器,在节点数量众多时尤其如此。存在可用的本地时间服务器时,修改节点的/etc/crhony.conf配置文件,并将时间服务器指向相应的主机即可,配置格式如下:
server CHRONY-SERVER-NAME-OR-IP iburst
3、主机名称解析
出于简化配置步骤的目的,本测试环境使用hosts文件进行各节点名称解析,文件内容如下所示:
192.168.6.240 master1.98yz.cn master1
192.168.6.241 linux-node1.98yz.cn node1
192.168.6.242 linux-node2.98yz.cn node2
4、关闭iptables或firewalld服务
在CentOS7上,iptables或firewalld服务通常只会安装并启动一种,在不确认具体启动状态的前提下,这里通过同时关闭并禁用二者即可简单达到设定目标。
~]# systemctl stop firewalld.service
~]# systemctl stop iptables.service
~]# systemctl disable firewalld.service
~]# systemctl disable iptables.service
5、关闭并禁用SELinux
若当前启用了SELinux,则需要编辑/etc/sysconfig/selinux文件,禁用SELinux,并临时设置其当前状态为permissive:
~]# sed -i 's@^\(SELINUX=\).*@\1disabled@' /etc/sysconfig/selinux
~]# setenforce 0
6、禁用Swap设备
部署集群时,kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备,否则,就需要在后文的kubeadm init及kubeadm join命令执行时额外使用相关的选项忽略检查错误。
关闭Swap设备,需要分两步完成。首先是关闭当前已启用的所有Swap设备:
~]# swapoff -a
而后编辑/etc/fstab配置文件,注释用于挂载Swap设备的所有行。
7、启用ipvs内核模块
创建内核模块载入相关的脚本文件/etc/sysconfig/modules/ipvs.modules,设定自动载入的内核模块。文件内容如下:
#!/bin/bash
ipvs_modules_dir="/usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs"
for i in $(ls $ipvs_modules_dir | sed -r 's@(.*).ko.xz@\1@'); do
/sbin/modinfo -F filename $i &> /dev/null
if [ $? -eq 0 ]; then
/sbin/modprobe $i
fi
done
修改文件权限,并手动为当前系统加载内核模块:
~]# chmod +x /etc/sysconfig/modules/ipvs.modules
~]# bash /etc/sysconfig/modules/ipvs.modules
二、安装程序包(在各主机上完成如下设定)
1、生成yum仓库配置
首先获取docker-ce的配置仓库配置文件:
~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker.repo
而后手动生成kubernetes的yum仓库配置文件/etc/yum.repos.d/kubernetes.repo,内容如下:
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
enabled=1
2、安装相关的程序包
Kubernetes会对经过充分验正的Docker程序版本进行认证,目前认证完成的最高版本是17.03,但docker-ce的最新版本已经高出了几个版本号。管理员可忽略此认证而直接使用最新版本的docker-ce程序,不过,建议根据后面的说明,将安装命令替换为安装17.03版。
~]# yum install docker-ce
~]# yum install kubelet kubeadm kubectl
如果要安装目前经过Kubernetes认证的docker-17版本,可以将上面第一条安装命令替换为如下命令:
~]# yum install -y --setopt=obsoletes=0 docker-ce-17.03.2.ce docker-ce-selinux-17.03.2.ce
docker部署实例:
~]# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
~]# wget -O /etc/yum.repos.d/kubernetes.repo http://down.sunrisenan.com/linux/kubernetes.repo
~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/test/Packages/docker-ce-18.09.8-3.el7.x86_64.rpm
~]# yum install -y docker-ce-18.09.8-3.el7.x86_64.rpm
三、配置并启动docker服务(在各节点执行)
若要通过默认的k8s.gcr.io镜像仓库获取Kubernetes系统组件的相关镜像,需要配置docker Unit File(/usr/lib/systemd/system/docker.service文件)中的Environment变量,为其定义合用的HTTPS_PROXY,格式如下:
Environment="HTTPS_PROXY=PROTOCOL://HOST:PORT"
Environment="NO_PROXY=172.20.0.0/16,127.0.0.0/8"
另外,docker自1.13版起会自动设置iptables的FORWARD默认策略为DROP,这可能会影响Kubernetes集群依赖的报文转发功能,因此,需要在docker服务启动后,重新将FORWARD链的默认策略设备为ACCEPT,方式是修改/usr/lib/systemd/system/docker.service文件,在“ExecStart=/usr/bin/dockerd”一行之后新增一行如下内容:
ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT
配置加速:
~]# cat > /etc/docker/daemon.json<<EOD
{
"registry-mirrors":["https:registry.docker-cn.com"]
}
重载完成后即可启动docker服务:
~]# systemctl daemon-reload
~]# systemctl start docker.service
而后设定docker和kubelet随系统引导自动启动:
~]# systemctl enable docker kubelet
四、初始化主节点(在master01上完成如下操作)
1、初始化master节点
若未禁用Swap设备,则需要编辑kubelet的配置文件/etc/sysconfig/kubelet,设置其忽略Swap启用的状态错误,内容如下:
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
(可选步骤)而后,在运行初始化命令之前先运行如下命令单独获取相关的镜像文件,而后再运行后面的kubeadm init命令,以便于观察到镜像文件的下载过程。
~]# kubeadm config images pull
而后即可进行master节点初始化。kubeadm init命令支持两种初始化方式,一是通过命令行选项传递关键的部署设定,另一个是基于yaml格式的专用配置文件,后一种允许用户自定义各个部署参数。下面分别给出了两种实现方式的配置步骤,建议读者采用第二种方式进行。
初始化方式一:
运行如下命令完成master01节点的初始化:
~]# kubeadm init --kubernetes-version=v1.15.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap
命令中的各选项简单说明如下:
(1) --kubernetes-version选项的版本号用于指定要部署的Kubenretes程序版本,它需要与当前的kubeadm支持的版本保持一致;
(2) --pod-network-cidr选项用于指定分Pod分配使用的网络地址,它通常应该与要部署使用的网络插件(例如flannel、calico等)的默认设定保持一致,10.244.0.0/16是flannel默认使用的网络;
(3) --service-cidr用于指定为Service分配使用的网络地址,它由kubernetes管理,默认即为10.96.0.0/12;
(4) 最后一个选项“--ignore-preflight-errors=Swap”仅应该在未禁用Swap设备的状态下使用。
初始化方式二:
kubeadm也可通过配置文件加载配置,以定制更丰富的部署选项。以下是个符合前述命令设定方式的使用示例,不过,它明确定义了kubeProxy的模式为ipvs,并支持通过修改imageRepository的值修改获取系统镜像时使用的镜像仓库。
apiVersion: kubeadm.k8s.io/v1beta2
kind: MasterConfiguration
kubernetesVersion: v1.15.3
api:
advertiseAddress: 192.168.6.240
bindPort: 6443
controlPlaneEndpoint: ""
imageRepository: k8s.gcr.io
kubeProxy:
config:
mode: "ipvs"
ipvs:
ExcludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
syncPeriod: 30s
kubeletConfiguration:
baseConfig:
cgroupDriver: cgroupfs
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
failSwapOn: false
resolvConf: /etc/resolv.conf
staticPodPath: /etc/kubernetes/manifests
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
apiVersion: kubeadm.k8s.io/v1beta2
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: master1.98yz.cn
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.15.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
scheduler: {}
将上面的内容保存于配置文件中,例如kubeadm-config.yaml,而后执行相应的命令:
~]# kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=Swap
注意:对于Kubernetes系统的新用户来说,无论使用上述哪种方法,命令运行结束后,请记录最后的kubeadm join命令输出的最后提示的操作步骤。下图的内容是需要用户记录的一个命令输出示例,它提示了后续需要的操作步骤:
Your Kubernetes control-plane 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/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.6.240:6443 --token j83ru0.ciiq5aho08upl2hr \
--discovery-token-ca-cert-hash sha256:fcc3ada487a6e3492489c9aa4aaf468233f2f14e2b6e115e0c5946a7e2fbe70c
另外,kubeadm init命令完整参考指南请移步官方文档。https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/。
2、初始化kubectl
kubectl是kube-apiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件/etc/kubernetes/admin.conf,它可由kubectl通过默认的“$HOME/.kube/config”的路径进行加载。当然,用户也可在kubectl命令上使用–kubeconfig选项指定一个别的位置。
下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下:
~]# mkdir ~/.kube
~]# cp /etc/kubernetes/admin.conf ~/.kube/config
而后,即可通过kubectl进行客户端命令测试,并借此了解集群组件的当前状态:
~]# kubectl get componentstatus
一个正常的输出应该类似如下输出结果所示:
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health": "true"}
3、添加flannel网络附件
Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上:
~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
而后使用如下命令确认其输出结果中Pod的状态为“Running”,类似如下所示:
~]# kubectl get pods -n kube-system -l app=flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-amd64-wscnz 1/1 Running 0 14m
4、验正master节点已经就绪
~]# kubectl get nodes
上述命令应该会得到类似如下输出:
NAME STATUS ROLES AGE VERSION
master1.98yz.cn Ready master 146m v1.15.3
五、添加节点到集群中(在node01和node02上分别完成如下操作)
1、忽略Swap相关的预检错误
若未禁用Swap设备,编辑kubelet的配置文件/etc/sysconfig/kubelet,设置其忽略Swap启用的状态错误,内容如下:
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
提示:若节点禁用了所有的Swap设备,并无须执行此步骤。
2、添加节点
将节点加入第二步中创建的master的集群中,要使用主节点初始化过程中记录的kubeadm join命令,并且在未禁用Swap设备的情况下,额外附加“–ignore-preflight-errors=Swap”选项;下面的命令来自于前面初始master时运行的kubeadm init命令的输出结果。
~]# kubeadm join 192.168.6.240:6443 --token j83ru0.ciiq5aho08upl2hr --discovery-token-ca-cert-hash sha256:fcc3ada487a6e3492489c9aa4aaf468233f2f14e2b6e115e0c5946a7e2fbe70c --ignore-preflight-errors=Swap
在每个节点添加完成后,即可通过kubectl验正添加结果。下面的命令及其输出是在node01和node02均添加完成后运行的,其输出结果表明两个Node已经准备就绪。
[root@master1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
linux-node1.98yz.cn Ready <none> 97m v1.15.3
linux-node2.98yz.cn Ready <none> 83m v1.15.3
master1.98yz.cn Ready master 146m v1.15.3
到此为止,一个master,并附带有两个node的kubernetes集群基础设施已经部署完成,用户随后即可测试其核心功能。例如,下面的命令可将myapp以Pod的形式编排运行于集群之上,并通过在集群外部进行访问
~]# kubectl create deployment myapp --image=ikubernetes/myapp:v1
~]# kubectl create service nodeport myapp --tcp=80:80
而后,使用如下命令了解Service对象myapp使用的NodePort,以便于在集群外部进行访问:
~]# kubectl get svc -l app=myapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp NodePort 10.110.139.4 <none> 80:30923/TCP 8s
myapp是一个web应用,因此,用户可以于集群外部通过http://NodeIP:30923
这个URL访问myapp上的应用,例如于集群外通过浏览器访问http://192.168.6.240:30923
。
六、不能使用代理
docker pull mirrorgooglecontainers/kube-apiserver-amd64:v1.15.3
docker pull mirrorgooglecontainers/kube-controller-manager-amd64:v1.15.3
docker pull mirrorgooglecontainers/kube-scheduler-amd64:v1.15.3
docker pull mirrorgooglecontainers/kube-proxy-amd64:v1.15.3
docker pull mirrorgooglecontainers/pause-amd64:3.1
docker pull mirrorgooglecontainers/etcd-amd64:3.3.10
docker pull coredns/coredns:1.3.1
docker tag mirrorgooglecontainers/kube-apiserver-amd64:v1.15.3 k8s.gcr.io/kube-apiserver:v1.15.3
docker tag mirrorgooglecontainers/kube-controller-manager-amd64:v1.15.3 k8s.gcr.io/kube-controller-manager:v1.15.3
docker tag mirrorgooglecontainers/kube-scheduler-amd64:v1.15.3 k8s.gcr.io/kube-scheduler:v1.15.3
docker tag mirrorgooglecontainers/kube-proxy-amd64:v1.15.3 k8s.gcr.io/kube-proxy:v1.15.3
docker tag mirrorgooglecontainers/pause-amd64:3.1 k8s.gcr.io/pause:3.1
docker tag mirrorgooglecontainers/etcd-amd64:3.3.10 k8s.gcr.io/etcd:3.3.10
docker tag coredns/coredns:1.3.1 k8s.gcr.io/coredns:1.3.1
docker image rm mirrorgooglecontainers/kube-apiserver-amd64:v1.15.3
docker image rm mirrorgooglecontainers/kube-controller-manager-amd64:v1.15.3
docker image rm mirrorgooglecontainers/kube-scheduler-amd64:v1.15.3
docker image rm mirrorgooglecontainers/kube-proxy-amd64:v1.15.3
docker image rm mirrorgooglecontainers/pause-amd64:3.1
docker image rm mirrorgooglecontainers/etcd-amd64:3.3.10
docker image rm coredns/coredns:1.3.1
报错
[root@master1 ~]# kubeadm init --kubernetes-version=v1.15.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12
[init] Using Kubernetes version: v1.15.3
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 19.03.1. Latest validated version: 18.09
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR Swap]: running with swap on is not supported. Please disable swap
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
[root@master1 ~]# vim /etc/sysconfig/kubelet
[root@master1 ~]# cat /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
[root@master1 ~]# kubeadm init --kubernetes-version=v1.15.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap
# Setup daemon.
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# Restart Docker
systemctl daemon-reload
systemctl restart docker