kubernetes环境搭建

kubernetes介绍

Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S。 K8S是Google内部一个叫Borg的容器集群管理系统衍生出来的,Borg已经在Google大规模生产运行十年之久。 K8S主要用于自动化部署、扩展和管理容器应用,提供了资源调度、部署管理、服务发现、扩容缩容、监控等一整套功能。 2015年7月,Kubernetes v1.0正式发布,截止到2017年9月29日最新稳定版本是v1.8。 Kubernetes目标是让部署容器化应用简单高效。 官方网站:www.kubernetes.io

kubernetes主要功能

  • 数据卷
    • Pod中容器之间共享数据,可以使用数据卷。
  • 应用程序健康检查
    • 容器内服务可能进程堵塞无法处理请求,可以设置监控检查策略保证应用健壮性。
  • 复制应用程序实例
    • 控制器维护着Pod副本数量,保证一个Pod或一组同类的Pod数量始终可用。
  • 弹性伸缩
    • 根据设定的指标(CPU利用率)自动缩放Pod副本数。
  • 服务发现
    • 使用环境变量或DNS服务插件保证容器中程序发现Pod入口访问地址。
  • 负载均衡
    • 一组Pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器。在集群内部其他Pod可通过这个ClusterIP访问应用。
  • 滚动更新
    • 更新服务不中断,一次更新一个Pod,而不是同时删除整个服务。
  • 服务编排
    • 通过文件描述部署服务,使得应用程序部署变得更高效。
  • 资源监控
    • Node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InfluxDB时序数据库,再由Grafana展示。
  • 提供认证和授权
    • 支持属性访问控制(ABAC)、角色访问控制(RBAC)认证授权策略。

基本对象概念

基本对象

  • Pod
    • Pod是最小部署单元,一个Pod有一个或多个容器组成,Pod中容器共享存储和网络,在同一台Docker主机上运行。
  • Service
    • Service一个应用服务抽象,定义了Pod逻辑集合和访问这个Pod集合的策略。
    • Service代理Pod集合对外表现是为一个访问入口,分配一个集群IP地址,来自这个IP的请求将负载均衡转发后端Pod中的容器。
    • Service通过Lable Selector选择一组Pod提供服务。
  • Volume
    • 数据卷,共享Pod中容器使用的数据。
  • Namespace
    • 命名空间将对象逻辑上分配到不同Namespace,可以是不同的项目、用户等区分管理,并设定控制策略,从而实现多租户。命名空间也称为虚拟集群。
  • Lable
    • 标签用于区分对象(比如Pod、Service),键/值对存在;每个对象可以有多个标签,通过标签关联象。

基于基本对象更高层次抽象

  • ReplicaSet
  • Deployment
  • StatefulSet
  • DaemonSet
  • Job

kubernetes部署

官方提供的几种Kubernetes部署方式

  • minikube

Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,尝试Kubernetes或日常开发的用户使用。不能用于生产环境。

官方地址:https://kubernetes.io/docs/setup/minikube/

  • kubeadm

Kubeadm也是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。

官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

  • 二进制包

从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。

小结: 生产环境中部署Kubernetes集群,只有Kubeadm和二进制包可选,Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。我们这里使用二进制包部署Kubernetes集群,我也是推荐大家使用这种方式,虽然手动部署麻烦点,但学习很多工作原理,更有利于后期维护。

软件环境

软件 版本
操作系统 CentOS7.5_x64
Docker 18-ce
Kubernetes 1.12

服务器角色

角色 IP 组件
k8s-master 192.168.31.63 kube-apiserver,kube-controller-manager,kube-scheduler,etcd
k8s-node1 192.168.31.65 kubelet,kube-proxy,docker,flannel,etcd
k8s-node2 192.168.31.66 kubelet,kube-proxy,docker,flannel,etcd

架构图

自签TLS证书

证书需求规划

组件 证书文件
kube-apiserver ca.pem,ca-key.pem,server.pem,server-key.pem
kube-controller-manager ca.pem,ca-key.pem
kube-scheduler -
etcd ca.pem,server.pem,server-key.pem
kubelet ca.pem,ca-key.pem
kube-proxy ca.pem,kube-proxy.pem,kube-proxy-key.pem
docker
flannel ca.pem,server.pem,server-key.pem
kubectl ca.pem,admin.pem,admin-key.pem

下载软件

1
2
3
4
5
6
7
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

生成CA证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
mkdir /opt/certificate/conf
cat > /opt/certificate/conf/ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > /opt/certificate/conf/ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O":"K8S",
"OU":"system"
}
]
}
EOF
#生成ca证书
cfssl gencert -initca /opt/certificate/conf/ca-csr.json | cfssljson -bare ca -

生成server证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#注意修改机器IP(内网,外网)
cat > /opt/certificate/conf/server-csr.json <<EOF
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",
"172.16.0.6",
"139.199.179.66",
"192.168.0.3",
"117.48.214.66",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O":"K8S",
"OU":"system"
}
]
}
EOF
#生成server证书
cfssl gencert -ca=/opt/certificate/conf/ca.pem -ca-key=/opt/certificate/conf/ca-key.pem -config=/opt/certificate/conf/ca-config.json -profile=kubernetes /opt/certificate/conf/server-csr.json | cfssljson -bare server

生成admin证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#创建admin相关证书
cat > /opt/certificate/conf/admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O":"system:masters",
"OU":"system"
}
]
}
EOF
#生成admin证书
cfssl gencert -ca=/opt/certificate/conf/ca.pem -ca-key=/opt/certificate/conf/ca-key.pem -config=/opt/certificate/conf/ca-config.json -profile=kubernetes /opt/certificate/conf/admin-csr.json | cfssljson -bare admin

生成kube-proxy证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#创建kube-proxy相关证书
cat > /opt/certificate/conf/kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O":"k8s",
"OU":"system"
}
]
}
EOF
#生成kube-proxy证书
cfssl gencert -ca=/opt/certificate/conf/ca.pem -ca-key=/opt/certificate/conf/ca-key.pem -config=/opt/certificate/conf/ca-config.json -profile=kubernetes /opt/certificate/conf/kube-proxy-csr.json | cfssljson -bare kube-proxy

生成metrics-server证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat > /opt/certificate/conf/metrics-server-csr.json <<EOF
{
"CN": "aggregator",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O":"k8s",
"OU":"system"
}
]
}
EOF
#生成kube-proxy证书
cfssl gencert -ca=/opt/certificate/conf/ca.pem -ca-key=/opt/certificate/conf/ca-key.pem -config=/opt/certificate/conf/ca-config.json -profile=kubernetes /opt/certificate/conf/metrics-server-csr.json | cfssljson -bare metrics-server
1
2
3
#将生成好的证书迁移到ssl目录
cd /opt/certificate/conf/
mv *.pem ../etcd

部署Etcd集群

以下部署步骤在规划的三个etcd节点操作一样,唯一不同的是etcd配置文件中的服务器IP要写当前的:

解压二进制包:

1
2
3
4
5
6
7
8
9
mkdir /root/software/etcd/conf
#创建快捷方式(方便后期扩展)
ln -s /root/software/etcd/ /opt/etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.3.13/etcd-v3.3.13-linux-amd64.tar.gz
#解压
tar zxvf etcd-v3.3.13-linux-amd64.tar.gz
#提出需文件-> opt/etcd/bin
mv etcd-v3.3.13-linux-amd64/{etcd,etcdctl} /opt/etcd/
chmod +x etcdctl etcd

创建etcd配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#注意修改机器IP,etcd只能部署单数否则无法选举
cat > /opt/etcd/conf/etcd.conf <<EOF
#[Member]
#节点名称
ETCD_NAME="etcd01"
#数据目录
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"

#集群通信监听地址
ETCD_LISTEN_PEER_URLS="https://172.16.0.6:2380"

#客户端访问监听地址
ETCD_LISTEN_CLIENT_URLS="https://172.16.0.6:2379"

#[Clustering]
#集群通告地址
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://139.199.179.66:2380"

#客户端通告地址
ETCD_ADVERTISE_CLIENT_URLS="https://139.199.179.66:2379"

#集群节点地址(多台机器用逗号连接,etcd02=https://117.48.214.66:2380)
ETCD_INITIAL_CLUSTER="etcd01=https://139.199.179.66:2380"

#集群Token
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

#加入集群的当前状态,new是新集群,existing表示加入已有集群
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
  • ETCD_NAME 节点名称
  • ETCD_DATA_DIR 数据目录
  • ETCD_LISTEN_PEER_URLS 集群通信监听地址
  • ETCD_LISTEN_CLIENT_URLS 客户端访问监听地址
  • ETCD_INITIAL_ADVERTISE_PEER_URLS 集群通告地址
  • ETCD_ADVERTISE_CLIENT_URLS 客户端通告地址
  • ETCD_INITIAL_CLUSTER 集群节点地址
  • ETCD_INITIAL_CLUSTER_TOKEN 集群Token
  • ETCD_INITIAL_CLUSTER_STATE 加入集群的当前状态,new是新集群,existing表示加入已有集群

systemd管理etcd:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
cat > /usr/lib/systemd/system/etcd.service  <<\EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/opt/etcd/conf/etcd.conf
ExecStart=/opt/etcd/etcd \
--name=${ETCD_NAME} \
--data-dir=${ETCD_DATA_DIR} \
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--initial-cluster=${ETCD_INITIAL_CLUSTER} \
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster-state=new \
--cert-file=/opt/certificate/server.pem \
--key-file=/opt/certificate/server-key.pem \
--peer-cert-file=/opt/certificate/server.pem \
--peer-key-file=/opt/certificate/server-key.pem \
--trusted-ca-file=/opt/certificate/ca.pem \
--peer-trusted-ca-file=/opt/certificate/ca.pem
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

配置etcd环境变量:

1
2
3
vi /etc/profile
PATH=$PATH:/disk/software/etcd
source /etc/profile

SSH互信:

1
2
3
4
ssh-keygen
ls /root/.ssh/
ssh-copy-id -p 22 root@117.48.214.66
scp

bash启动并设置开启启动:

1
2
systemctl start etcd
systemctl enable etcd

都部署完成后,检查etcd集群状态:

1
2
3
4
/opt/etcd/etcdctl \
--ca-file=/opt/certificate/ca.pem --cert-file=/opt/certificate/server.pem --key-file=/opt/certificate/server-key.pem \
--endpoints="https://172.16.0.6:2379" \
cluster-health

如果输出上面信息,就说明集群部署成功。如果有问题第一步先看日志:/var/log/message 或 journalctl -u etcd

部署Flannel网络

网络术语概念

  • 二层交换技术
    • 工作在OSI七层网络模型的第二层,通过MAC地址进行帧转发。
  • 三层交换技术
    • 也称为IP交换技术,工作在OSI七层网络模型的第三层,通过IP地址进行包转发。它解决了局域网中网段划分之后,网段中子网必须依赖路由器进行管理的局面。
  • 网桥(Bridge)
    • 工作在OSI七层网络模型的第二层,根据MAC地址转发,类似于二层交换机。Linux网桥将不同的网络口连接起来,连接的网络接口可以来自不同的局域网,网桥决定了接收的数据包是转发给同一个局域网内主机还是别的网络上。
  • VLAN( Virtual Local Area Network,虚拟局域网)
    • 在物理网络(通常路由器接口)基础上建立一个或多个逻辑子网,将一个大的广播域切分若干小的广播域。一个VLAN就是一个广播域,VLAN之间通信通过三层路由器来完成。

**Overlay Network **

  • Overlay Network

    • 覆盖网络,在基础网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链路连接起来。
  • VXLAN

    • 数据包封装到UDP中,并使用物理网络的IP/MAC作为外层报文头进行封装,然后在IP网络上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。
  • Flannel

    • 是Overlay网络的一种,也是将源数据包封装在另外一种网络包里面进行路由转发和通讯,目前已经支持UDP、VXLAN、AWS、VPC和GCE路由等数据转发方式。
  • 多主机容器网络通讯其他主流方案

    • 隧道方案(Weave、OpenvSwith),路由方案(Calico)

工作原理:

部署配置

Falnnel要用etcd存储自身一个子网信息,所以要保证能成功连接Etcd,写入预定义子网段:

1
2
3
4
5
#只需要在master上执行
/opt/etcd/etcdctl \
--ca-file=/opt/certificate/ca.pem --cert-file=/opt/certificate/server.pem --key-file=/opt/certificate/server-key.pem \
--endpoints="https://172.16.0.6:2379" \
set /coreos.com/network/config '{ "Network": "172.1.0.0/16", "Backend": {"Type": "vxlan"}}'

下载二进制包:

1
2
3
4
5
6
7
8
mkdir  /root/software/flannel/conf
#创建快捷方式(方便后期扩展)
ln -s /root/software/flannel/ /opt/flannel
wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
#解压
tar zxvf flannel-v0.11.0-linux-amd64.tar.gz
mv flanneld mk-docker-opts.sh /opt/flannel
chmod +x flanneld mk-docker-opts.sh

将主节点上的证书以及flannel传输到当前node节点

1
2
3
4
5
#传输目标文件必须存在
scp /opt/certificate/ root@117.48.214.66:/opt/certificate
scp /opt/flannel/conf/ root@117.48.214.66:/opt/flannel/conf
#如果报错 -bash: ssh-copy-id: command not found 安装客户端即可
yum -y install openssh-clients

配置Flannel:

1
2
3
cat > /opt/flannel/conf/flanneld.conf <<EOF
FLANNEL_OPTIONS="--etcd-endpoints=https://172.16.0.6:2379 -etcd-cafile=/opt/certificate/ca.pem -etcd-certfile=/opt/certificate/server.pem -etcd-keyfile=/opt/certificate/server-key.pem --public-ip=139.199.179.66 -iface=eth0"
EOF

systemd管理Flannel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat > /usr/lib/systemd/system/flanneld.service <<\EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service

[Service]
Type=notify
EnvironmentFile=/opt/flannel/conf/flanneld.conf
ExecStart=/opt/flannel/flanneld --ip-masq $FLANNEL_OPTIONS
ExecStartPost=/opt/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

配置Docker启动指定子网段:

1
2
3
4
5
vi /usr/lib/systemd/system/docker.service
[Service]
EnvironmentFile=/run/flannel/subnet.env
#注:ecStart后面加 $DOCKER_NETWORK_OPTIONS 即可
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS

重启flannel和docker:

1
2
3
4
systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker

部署kubernetes-master

部署apiserver组件

下载二进制包:

1
2
3
4
5
6
7
8
wget https://dl.k8s.io/v1.15.0-beta.2/kubernetes-server-linux-amd64.tar.gz
tar zxvf kubernetes-server-linux-amd64
mkdir -p /root/software/kubernetes/{master,node}
mkdir /root/software/kubernetes/master/conf
mkdir /root/software/kubernetes/node/conf
#提取 kubernetes-server-linux-amd64中的 kubernetes/server/bin
cp kube-apiserver kube-controller-manager kube-scheduler /root/software/kubernetes/master
cp kubectl kube-proxy kube-scheduler /root/software/kubernetes/node

生成token:

1
2
3
4
5
6
export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
cat /root/software/kubernetes/token.csv
5f75639ff311b557134e062c48692401,kubelet-bootstrap,10001,"system:kubelet-bootstrap"

参数说明:

  • 5f75639ff311b557134e062c48692401 随机字符串,自己可生成
  • kubelet-bootstrap 用户名
  • 10001 UID
  • system:kubelet-bootstrap 用户组

创建apiserver配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#配置好前面生成的证书,确保能连接etcd。
cat > /opt/kubernetes/master/conf/kube-apiserver.conf <<\EOF
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=http://127.0.0.1:2379 \
--bind-address=0.0.0.0 \
--secure-port=6443 \
--advertise-address=139.199.179.66 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/24 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth \
--token-auth-file=/opt/kubernetes/token.csv \
--service-node-port-range=1-50000 \
--tls-cert-file=/opt/certificate/server.pem \
--tls-private-key-file=/opt/certificate/server-key.pem \
--client-ca-file=/opt/certificate/ca.pem \
--service-account-key-file=/opt/certificate/ca-key.pem \
--etcd-cafile=/opt/certificate/ca.pem \
--etcd-certfile=/opt/certificate/server.pem \
--etcd-keyfile=/opt/certificate/server-key.pem \
--requestheader-client-ca-file=/opt/certificate/ca.pem \
--requestheader-allowed-names=aggregator \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--enable-aggregator-routing=true \
--proxy-client-cert-file=/opt/certificate/metrics-server.pem \
--proxy-client-key-file=/opt/certificate/metrics-server-key.pem \"
EOF

参数说明:

  • –logtostderr 启用日志
  • —v 日志等级
  • –etcd-servers etcd集群地址
  • –bind-address 监听地址
  • –secure-port https安全端口
  • –advertise-address 集群通告地址
  • –allow-privileged 启用授权
  • –service-cluster-ip-range Service虚拟IP地址段
  • –enable-admission-plugins 准入控制模块
  • –authorization-mode 认证授权,启用RBAC授权和节点自管理
  • –enable-bootstrap-token-auth 启用TLS bootstrap功能,后面会讲到
  • –token-auth-file token文件
  • –service-node-port-range Service Node类型默认分配端口范围
  • –requestheader-XXX、–proxy-client-XXX 是 kube-apiserver 的 aggregator layer 相关的配置参数,metrics-server & HPA 需要使用;
  • –requestheader-client-ca-file:用于签名 –proxy-client-cert-file 和 –proxy-client-key-file 指定的证书;在启用了 metric aggregator 时使用;
  • 如果 kube-apiserver 机器没有运行 kube-proxy,则还需要添加 –enable-aggregator-routing=true 参数

systemd管理apiserver:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /usr/lib/systemd/system/kube-apiserver.service <<\EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=/opt/kubernetes/master/conf/kube-apiserver.conf
ExecStart=/opt/kubernetes/master/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

启动:

1
2
3
systemctl daemon-reload
systemctl enable kube-apiserver
systemctl restart kube-apiserver

部署controller-manager组件

创建controller-manager配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /opt/kubernetes/master/conf/kube-controller-manager.conf <<\EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \
--leader-elect=true \
--address=127.0.0.1 \
--service-cluster-ip-range=10.0.0.0/24 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/certificate/ca.pem \
--cluster-signing-key-file=/opt/certificate/ca-key.pem \
--root-ca-file=/opt/certificate/ca.pem \
--service-account-private-key-file=/opt/certificate/ca-key.pem \
--horizontal-pod-autoscaler-use-rest-clients=true"
EOF

参数说明:

  • leader-elect 多个组件存在用户选举
  • address 连接地址
  • service-cluster 监听地址

systemd管理controller-manager组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /usr/lib/systemd/system/kube-controller-manager.service <<\EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/master/conf/kube-controller-manager.conf
ExecStart=/opt/kubernetes/master/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

启动:

1
2
3
systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl restart kube-controller-manager

部署scheduler组件

创建schduler配置文件:

1
2
3
4
5
6
cat > /opt/kubernetes/master/conf/kube-scheduler.conf <<\EOF
KUBE_SCHEDULER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \
--leader-elect"
EOF

参数说明:

  • –master 连接本地apiserver
  • –leader-elect 当该组件启动多个时,自动选举(HA)

systemd管理schduler组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /usr/lib/systemd/system/kube-scheduler.service <<\EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/master/conf/kube-scheduler.conf
ExecStart=/opt/kubernetes/master/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

启动:

1
2
3
systemctl daemon-reload
systemctl enable kube-scheduler
systemctl restart kube-scheduler

设置全局可用kubectl

1
2
3
4
5
6
7
8
vi /etc/profile
#添加下面行
export PATH=/data-disk/software/kubernetes:$PATH
source /etc/profile

#添加命令行自动补全
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

所有组件都已经启动成功,通过kubectl工具查看当前集群组件状态:

1
2
3
4
5
[root@imaxun-qcloud kubernetes]# kubectl get cs
NAME STATUS MESSAGE ERROR
etcd-0 Healthy {"health":"true"}
scheduler Healthy ok
controller-manager Healthy ok

部署kubernetes-node

流程概念

Master apiserver启用TLS认证后,Node节点kubelet组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,当Node节点很多时,签署证书是一件很繁琐的事情,因此有了TLS Bootstrapping机制,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。

认证大致工作流程如图所示:

kubelet-bootstrap用户绑定到系统集群角色

1
2
3
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap

创建kubeconfig文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
cd /opt/kubernetes/node/conf
# 创建kubelet bootstrapping kubeconfig
export BOOTSTRAP_TOKEN=5f75639ff311b557134e062c48692401
export KUBE_APISERVER="https://139.199.179.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/certificate/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=bootstrap.kubeconfig

# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig

# 设置默认上下文
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

#----------------------

# 创建kube-proxy kubeconfig文件

kubectl config set-cluster kubernetes \
--certificate-authority=/opt/certificate/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig

kubectl config set-credentials kube-proxy \
--client-certificate=/opt/certificate/kube-proxy.pem \
--client-key=/opt/certificate/kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig

kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig

kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
# ls
bootstrap.kubeconfig kube-proxy.kubeconfig

部署kubelet组件

配置主机名

1
2
3
4
vi /etc/hosts
#在原有配置后面添加
139.199.179.66 imaxun-qcloud imaxun-qcloud
117.48.214.66 imaxun-jdcloud imaxun-jdcloud

创建kubelet配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /opt/kubernetes/node/conf/kubelet.conf <<\EOF
KUBELET_OPTS="--logtostderr=true \
--v=4 \
--address=0.0.0.0 \
--hostname-override=imaxun-qcloud \
--kubeconfig=/opt/kubernetes/conf/node/kubelet.kubeconfig \
--experimental-bootstrap-kubeconfig=/opt/kubernetes/conf/node/bootstrap.kubeconfig \
--cert-dir=/opt/kubernetes/conf/node/certificate \
--allow-privileged=true \
--cluster-dns=10.0.0.2 \
--cluster-domain=cluster.local \
--fail-swap-on=false \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
EOF

参数说明:

  • –hostname-override 在集群中显示的主机名
  • –kubeconfig 指定kubeconfig文件位置,会自动生成
  • –bootstrap-kubeconfig 指定刚才生成的bootstrap.kubeconfig文件
  • –cert-dir 颁发证书存放位置
  • –pod-infra-container-image 管理Pod网络的镜像

其中/opt/kubernetes/cfg/kubelet.config配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 192.168.31.65
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS: ["10.0.0.2"]
clusterDomain: cluster.local.
failSwapOn: false
authentication:
anonymous:
enabled: true

systemd管理kubelet组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat > /usr/lib/systemd/system/kubelet.service <<\EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/opt/kubernetes/node/conf/kubelet.conf
ExecStart=/opt/kubernetes/node/kubelet $KUBELET_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

启动:

1
2
3
systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet

在Master审批Node加入集群:

启动后还没加入到集群中,需要手动允许该节点才可以。 在Master节点查看请求签名的Node:

1
2
3
kubectl get csr
kubectl certificate approve node-csr-Ti1zfmUCNQzWdKKWz253zuLBGh1Xq9MaM39r-7CpG6Q
kubectl get node

部署kube-proxy组件

创建kube-proxy配置文件:

1
2
3
4
5
6
7
cat > /opt/kubernetes/node/conf/kube-proxy.conf << \EOF
KUBE_PROXY_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=imaxun-qcloud \
--cluster-cidr=10.0.0.0/24 \
--kubeconfig=/opt/kubernetes/conf/node/kube-proxy.kubeconfig"
EOF

systemd管理kube-proxy组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /usr/lib/systemd/system/kube-proxy.service <<\EOF
[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
EnvironmentFile=/opt/kubernetes/node/conf/kube-proxy.conf
ExecStart=/opt/kubernetes/node/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

启动:

1
2
3
systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy

kubectl远程连接集群

1
2
3
4
5
6
7
8
#设置集群项中名为kubernetes的apiserver地址与根证书
kubectl config set-cluster kubernetes --server=https://139.199.179.66 --certificate-authority=/opt/certificate/ca.pem
#设置用户项中cluster-admin用户证书认证字段
kubectl config set-credentials cluster-admin --certificate=authority=/opt/certificate/ca.pem --client-key=/opt/certificate/admin-key.pem
#设置环境项中名为default的默认集群和用户
kubectl config set-context defaulf --cluster=kubernetes --user=cluster-admin
#设置默认环境项为default
kubectl config use-context defaulf

kubectl常用命令

类型 命令 描述
基础命令 create 通过文件名或标准输入创建资源
expose 将一个资源公开为一个新的Kubernetes服务
run 创建并运行一个特定的镜像,可能是副本
创建一个deployment或job管理创建的容器
get 显示一个或多个资源
explain 文档参考资料
get 显示一个或多个资源
edit 使用默认的编辑器编辑一个资源
delete 通过文件名、标准输入、资源名称或标签选择器来删除资源
部署命令 rollout 管理资源的发布
rolling-update 执行指定复制控制的滚动更新
scale 扩容或缩容Pod数量,Deployment、ReplicaSet、RC或Job
autoscale 创建一个自动选择扩容或缩容并设置Pod数量
集群管理命令 certificate 修改证书资源
cluster-info 显示集群信息
top 显示资源(CPU/Memory/Storage)使用。需要Heapster运行
cordon 标记节点不可调度
uncordon 标记节点可调度
drain 维护期间排除节点
taint
类型 命令 描述
故障诊断和调试命令 describe 显示特定资源或资源组的详细信息
logs 在pod或指定的资源中容器打印日志。如果pod只有一个容器,容器名称是可选的
attach 附加到一个进程到一个已经运行的容器
exec 执行命令到容器
port-forward 转发一个或多个本地端口到一个pod
proxy 为kubernetes API Server启动服务代理
cp 拷贝文件或目录到容器中
auth 检查授权
高级命令 apply 通过文件名或标准输入对资源应用配置
patch 使用补丁修改、更新资源的字段
replace 通过文件名或标准输入替换一个资源
convert 不同的API版本之间转换配置文件。YAML和JSON格式都接受
设置命令 label 更新资源上的标签
annotate 在一个或多个资源上更新注释
completion 用于实现kubectl工具自动补全
其他命令 api-versions 打印受支持的API版本
config 修改kubeconfig文件(用于访问API,比如配置认证信息)
help 所有命令帮助
plugin 运行一个命令行插件。
version 打印客户端和服务版本信息

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 运行应用程序
kubectl run hello-world --replicas=3 --labels="app=example" --image=nginx:1.10 --port=80
# 显示有关Deployments信息
kubectl get deployments hello-world
kubectl describe deployments hello-world
# 显示有关ReplicaSet信息
kubectl get replicasets
kubectl describe replicasets
# 创建一个Service对象暴露Deployment(在88端口负载TCP流量)
kubectl expose deployment hello-world --port=88 --type=NodePort --target-port=80 --name=example-service
# 创建一个Service对象暴露Deployment(在4100端口负载UDP流量)
kubectl expose deployment hello-world --port=4100 --type=NodePort --protocol=udp --target-port=80 --
name=example-service
# 显示有关Service信息
kubectl describe services example-service
# 使用节点IP和节点端口访问应用程序
curl http://<public-node-ip>:<node-port>

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 列出运行应用程序的pod
kubectl get pods --selector="app=example" --output=wide
# 查看pods所有标签
kubectl get pods --show-labels
# 根据标签查看pods
kubectl get pods -l app=example
# 扩容Pod副本数
kubectl scale deployment --replicas=10 hello-world
# 清理应用程序
kubectl delete services example-service
kubectl delete deployment hello-world
#
kubectl get pods -o wide --all-namespaces
#创建证书
kubectl create secret tls imaxun.com --cert=fullchain.cer --key=imaxun.com.key
#修改主机名
hostnamectl set-hostname imaxun-qcloud1
#设置lb权限
kubectl label nodes imaxun-qcloud node-role.kubernetes.io/lb=lb-qcloud

#创建腾讯云秘钥
kubectl create secret docker-registry qcloud --docker-server=ccr.ccs.tencentyun.com --docker-username=100001149985 --docker-password=xxx -n default
--docker-server: 仓库地址
--docker-username: 仓库登陆账号
--docker-password: 仓库登陆密码
--docker-email: 邮件地址(选填)
-n 命名空间

#docker 腾讯云推送镜像
docker login --username=100001149985 ccr.ccs.tencentyun.com
docker tag [ImageId] ccr.ccs.tencentyun.com/imaxun/hexo:[tag]
docker push ccr.ccs.tencentyun.com/imaxun/hexo:[tag]