k8s 安装

使用kubeadm安装kubernetes集群

系统: Centos7
官方文档

环境准备

关闭防火墙(如果开了的话)

systemctl stop firewalld  
systemctl disable firewalld  

关闭 SELinux

setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

关闭swap

swapoff -a
sed -i "s/\(^.*swap.*$\)/#\1/" /etc/fstab

加载内核相关模块

modprobe br_netfilter  
modprobe  ip_vs     
modprobe  ip_vs_rr  
modprobe  ip_vs_wrr  
modprobe  ip_vs_sh  
modprobe  nf_conntrack_ipv4

modprobe br_netfilter

ipv4/v6 arp包转发过滤.

modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh

4层负载均衡

modprobe nf_conntrack_ipv4 或 modprobe nf_conntrack 内核>=4.19

nf_conntrack(在老版本的 Linux 内核中叫 ip_conntrack)是一个内核模块,用于跟踪一个连接的状态的。连接状态跟踪可以供其他模块使用,最常见的两个使用场景是 iptables 的 nat 的 state 模块。 iptables 的 nat 通过规则来修改目的/源地址,但光修改地址不行,我们还需要能让回来的包能路由到最初的来源主机。这就需要借助 nf_conntrack 来找到原来那个连接的记录才行。而 state 模块则是直接使用 nf_conntrack 里记录的连接的状态来匹配用户定义的相关规则.
Iptables之nf_conntrack模块

更改系统参数

系统参数与上述加载的内核模块有关.
/etc/sysctl.conf

cat <<EOF >> /etc/sysctl.conf  
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

参数生效: sysctl -p

安装docker

添加docker源

yum -y install yum-utils  
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

查看docker版本

yum list docker-ce --showduplicates|sort -r 

安装指定的docker版本

根据kubernetes版本安装对应版本的docker. 具体信息可以查看 https://github.com/kubernetes/kubernetes/releases 查看对应版本的changelog. 目前相对比较稳定, 以下截取的16版本的log:

Unchanged
The list of validated docker versions remains unchanged.
The current list is 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09. (#72823, #72831)
CNI remains unchanged at v0.7.5. (#75455)
cri-tools remains unchanged at v1.14.0. (#75658)
……
kubernetes/CHANGELOG-1.16.md

这边安装了docker18的版本

yum install -y docker-ce-18.09.9  
systemctl enable docker && systemctl start docker  

kubeadm安装kubernetes

安装kubeadm和kubelet

添加kubernets源, 这里使用了的是阿里的kubernetes源.

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 install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

systemctl enable kubelet && systemctl start kubelet

yum -y install ipset
yum -y install ipvsadm

docker的cgroup driver

cgroup driver和引入的问题

cgroup控制进程资源的使用, 具体实现的方式有两种driver, systemd和cgroupfs.

在kubelet(kubernetes中控制容器生命周期组件)中可以配置cgroup的driver. docker默认设置中也有driver的设置. [kubelet控制一套runc接口, docker实现了一套runc的接口. –> kubelet控制docker]

在两者配置的driver不同时, 会导致安装kubernetes时报错.

failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"

这个问题的解决, 使docker和kubelet中配置参数一致即可, 都为systemd或都为cgroupfs.

默认情形下, kubelet中cgroup driver使用的是systemd, 而docker中使用的是cgroupfs的driver.

kubernetes推荐使用的是systemd作为cgroup的driver.

Cgroup 驱动程序 当某个 Linux 系统发行版使用 systemd 作为其初始化系统时,初始化进程会生成并使用一个 root 控制组 (cgroup),并充当 cgroup 管理器。 systemd 与 cgroup 集成紧密,并将为每个进程分配 cgroup。 您也可以配置容器运行时和 kubelet 使用 cgroupfs。 连同 systemd 一起使用 cgroupfs 意味着将有两个不同的 cgroup 管理器。 控制组用来约束分配给进程的资源。 单个 cgroup 管理器将简化分配资源的视图,并且默认情况下将对可用资源和使用中的资源具有更一致的视图。 当有两个管理器时,最终将对这些资源产生两种视图。 在此领域我们已经看到案例,某些节点配置让 kubelet 和 docker 使用 cgroupfs,而节点上运行的其余进程则使用 systemd;这类节点在资源压力下会变得不稳定。 更改设置,令容器运行时和 kubelet 使用 systemd 作为 cgroup 驱动,以此使系统更为稳定。 请注意在 docker 下设置 native.cgroupdriver=systemd 选项。 警告: 强烈建议不要更改已加入集群的节点的 cgroup 驱动。 如果 kubelet 已经使用某 cgroup 驱动的语义创建了 pod,尝试更改运行时以使用别的 cgroup 驱动,为现有 Pods 重新创建 PodSandbox 时会产生错误。 重启 kubelet 也可能无法解决此类问题。 推荐将工作负载逐出节点,之后将节点从集群中删除并重新加入。

官网中文
官网英文

修改docker

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "registry-mirrors": ["https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn"]
}
EOF

Change default cgroup driver to systemd and verify parity w/docker on preflight

修改kubelet

默认不需要修改kubelet参数, 如果需要, 可以参考下面方式进行修改.

配置文件路径:

/etc/systemd/system/kubelet.service.d/10-kubeadm.conf  
/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf  

网上配置文件路径1居多, 在centos7安装中查找到的是路径2.

举例将kubelet中driver修改为systemd.
config中添加 –cgroup-driver=systemd

[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --cgroup-driver=systemd"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
......

cgroup driver选取: systemd vs cgroupfs

No results docker cgroup driver discussion - cgroupfs or systemd

重新加载服务 systemctl daemon-reload和 systemctl restart xxx

见标题

kubeadm初始化集群

上述命令需要在每个节点上执行. 以下命令初始化kubenetes集群, 只需要在主节点上运行初始化命令即可, 集群初始化完成后, 其他节点通过kubeadm join命令加入集群即可.

 kubeadm init  --image-repository  registry.aliyuncs.com/google_containers --pod-network-cidr=192.168.0.0/16

命令成功后会输出下面.

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 xxxxx:6443 --token gf7pwf.dix9uzxq50u47n2f \
    --discovery-token-ca-cert-hash sha256:3166fc496e1b6613fc0e7173eb4f750535cd0df2f9ceb09564873e35dfa5581b

root账户:

  mkdir -p $HOME/.kube
  cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  chown $(id -u):$(id -g) $HOME/.kube/config

非root账户:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

其他节点使用kubeadmin join命令加入集群.

通过命令查看集群信息

[root@node201 charts]# kubectl cluster-info
Kubernetes master is running at https://xxxx:6443
KubeDNS is running at https://xxxx:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

[root@node201 charts]# kubectl get node
NAME      STATUS   ROLES    AGE     VERSION
node201   Ready    master   2m16s   v1.17.0
node202   Ready    <none>   52s     v1.17.0
node203   Ready    <none>   90s     v1.17.0

[root@node201 charts]# kubectl get pod -n kube-system -o wide
NAME                              READY   STATUS              RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
coredns-9d85f5447-tpc9p           0/1     ContainerCreating   0          2m18s   <none>        node201   <none>           <none>
coredns-9d85f5447-wg5c2           0/1     ContainerCreating   0          2m18s   <none>        node201   <none>           <none>
etcd-node201                      1/1     Running             0          2m25s   10.0.40.201   node201   <none>           <none>
kube-apiserver-node201            1/1     Running             0          2m24s   10.0.40.201   node201   <none>           <none>
kube-controller-manager-node201   1/1     Running             0          2m24s   10.0.40.201   node201   <none>           <none>
kube-proxy-5hvp4                  1/1     Running             0          74s     10.0.40.202   node202   <none>           <none>
kube-proxy-6vgc8                  1/1     Running             0          112s    10.0.40.203   node203   <none>           <none>
kube-proxy-hxsnm                  1/1     Running             0          2m17s   10.0.40.201   node201   <none>           <none>
kube-scheduler-node201            1/1     Running             0          2m24s   10.0.40.201   node201   <none>           <none>

这里的coredns的容器没有起来的.

部署网络插件calico

kubectl apply -f https://docs.projectcalico.org/v3.10/manifests/calico.yaml  

网络安装好之后, coredns的相关容器也启动起来了.

[root@node201 charts]# kubectl get pod -n kube-system -o wide
NAME                                       READY   STATUS    RESTARTS   AGE     IP              NODE      NOMINATED NODE   READINESS GATES
calico-kube-controllers-74c9747c46-h7577   0/1     Running   0          65s     192.168.244.1   node202   <none>           <none>
calico-node-7stvb                          1/1     Running   0          65s     10.0.40.203     node203   <none>           <none>
calico-node-jncrb                          1/1     Running   0          65s     10.0.40.202     node202   <none>           <none>
calico-node-z2xpq                          1/1     Running   0          65s     10.0.40.201     node201   <none>           <none>
coredns-9d85f5447-tpc9p                    0/1     Running   0          3m35s   192.168.161.2   node201   <none>           <none>
coredns-9d85f5447-wg5c2                    1/1     Running   0          3m35s   192.168.161.1   node201   <none>           <none>
etcd-node201                               1/1     Running   0          3m42s   10.0.40.201     node201   <none>           <none>
kube-apiserver-node201                     1/1     Running   0          3m41s   10.0.40.201     node201   <none>           <none>
kube-controller-manager-node201            1/1     Running   0          3m41s   10.0.40.201     node201   <none>           <none>
kube-proxy-5hvp4                           1/1     Running   0          2m31s   10.0.40.202     node202   <none>           <none>
kube-proxy-6vgc8                           1/1     Running   0          3m9s    10.0.40.203     node203   <none>           <none>
kube-proxy-hxsnm                           1/1     Running   0          3m34s   10.0.40.201     node201   <none>           <none>
kube-scheduler-node201                     1/1     Running   0          3m41s   10.0.40.201     node201   <none>           <none>

存储插件 ceph

存储插件非必选, 了解.
ceph

开启ipvs

为什么使用ipvs代替iptable?

ipvs可以带来性能上的提升, kubernetes默认的是使用iptables, 当集群达到一定规模后, iptables可能会带来管理运维上的灾难.

有几种可以实现的方式, 这里展示编辑configmap的方式, 同时, 在kubeadm init时也可以指定参数.

安装工具ipset, ipvsadm(前面已安装):

yum -y install ipset
yum -y install ipvsadm

编辑configmap

编辑kube-proxy configmap, 将mode字段值改为ipvs. [默认为空]

[root@node201 ~]# kubectl get cm -n kube-system
NAME                                 DATA   AGE
calico-config                        4      6m48s
coredns                              1      148m
extension-apiserver-authentication   6      148m
kube-proxy                           2      148m
kubeadm-config                       2      148m
kubelet-config-1.17                  1      148m
[root@host-10-0-40-201 ~]# kubectl edit cm kube-proxy -n kube-system
configmap/kube-proxy edited

重启kube-proxy pod. (删除pod后, 会自动新建pod)

查看新kube-proxy日志, 显示Using ipvs Proxier.

[root@node201 ~]# kubectl logs kube-proxy-dlv4k -n kube-system
I1231 05:47:33.918206       1 node.go:135] Successfully retrieved node IP: 10.0.40.202
I1231 05:47:33.918288       1 server_others.go:172] Using ipvs Proxier.
W1231 05:47:33.918595       1 proxier.go:414] clusterCIDR not specified, unable to distinguish between internal and external traffic
W1231 05:47:33.918615       1 proxier.go:420] IPVS scheduler not specified, use rr by default
I1231 05:47:33.918934       1 server.go:571] Version: v1.17.0
I1231 05:47:33.919484       1 conntrack.go:52] Setting nf_conntrack_max to 131072
I1231 05:47:33.919800       1 config.go:313] Starting service config controller
I1231 05:47:33.919834       1 shared_informer.go:197] Waiting for caches to sync for service config
I1231 05:47:33.919871       1 config.go:131] Starting endpoints config controller
I1231 05:47:33.919892       1 shared_informer.go:197] Waiting for caches to sync for endpoints config
I1231 05:47:34.020030       1 shared_informer.go:204] Caches are synced for service config
I1231 05:47:34.020145       1 shared_informer.go:204] Caches are synced for endpoints config

可以通过ipvsadm -ln查看信息.

[root@node201 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 10.0.40.201:6443             Masq    1      0          0
TCP  10.96.0.10:53 rr
  -> 192.168.207.193:53           Masq    1      0          0
  -> 192.168.207.194:53           Masq    1      0          0
TCP  10.96.0.10:9153 rr
  -> 192.168.207.193:9153         Masq    1      0          0
  -> 192.168.207.194:9153         Masq    1      0          0
UDP  10.96.0.10:53 rr
  -> 192.168.207.193:53           Masq    1      0          0
  -> 192.168.207.194:53           Masq    1      0          0

更多关于ipvs和iptables可以了解: ipvs 基本介绍如何在 kubernetes 中启用 ipvs

关于kubeadm的配置

kubeadm的配置可以修改镜像仓库, ipvs的设置的.
通过导出默认配置, 然后修改默认配置.

kubeadm config print init-defaults > kubeadm.yaml
......
kubeadm init --config kubeadm.yaml

Helm安装

helm用户指南
使用Helm管理kubernetes应用

Helm是一个kubernetes应用的包管理工具,用来管理charts——预先配置好的安装包资源,有点类似于Ubuntu的APT和CentOS中的yum。

Helm chart是用来封装kubernetes原生应用程序的yaml文件,可以在你部署应用的时候自定义应用程序的一些metadata,便与应用程序的分发。

Helm和charts的主要作用: 应用程序封装
版本管理
依赖检查
便于应用程序分发

每一个版本 release, Helm 提供多种操作系统的二进制版本。这些二进制版本可以手动下载和安装。

下载想要的版本 https://github.com/helm/helm/releases, 解压缩(tar -zxvf helm-v2.0.0-linux-amd64.tgz). helm 在解压后的目录中找到二进制文件,并将其移动到所需的位置(mv linux-amd64/helm /usr/local/bin/helm).

以下以2.16版本为例.
PS: Helm v2与v3区别较大. 自行谷歌学习.

wget https://get.helm.sh/helm-v2.16.3-linux-amd64.tar.gz
tar -xzvf helm-v2.16.3-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/helm
helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.3 --stable-repo-url http://mirror.azure.cn/kubernetes/charts/

如果有问题再执行.

kubectl create serviceaccount --namespace kube-system tiller  
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller  
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'  

forbidden: User “system:serviceaccount:kube-system:default” cannot get namespaces in the namespace “default

参考:
https://whmzsu.github.io/helm-doc-zh-cn/quickstart/install-zh_cn.html https://github.com/helm/helm/issues/3130

镜像加速

https://www.ilanni.com/?p=14534