专业的编程技术博客社区

网站首页 > 博客文章 正文

带证书的二进制方式安装部署k8s

baijin 2024-12-31 09:10:38 博客文章 6 ℃ 0 评论

带证书的二进制方式安装部署k8s

1.配置固定IP

cd /etc/sysconfig/network-scripts/

TYPE=Ethernet

PROXY_METHOD=none

BROWSER_ONLY=no

#BOOTPROTO=dhcp

BOOTPROTO=static

DEFROUTE=yes

IPV4_FAILURE_FATAL=no

IPV6INIT=yes

IPV6_AUTOCONF=yes

IPV6_DEFROUTE=yes

IPV6_FAILURE_FATAL=no

IPV6_ADDR_GEN_MODE=stable-privacy

NAME=ens33

DEVICE=ens33

ONBOOT=yes

IPADDR0=192.168.10.6

PREFIXO0=24

GATEWAY0=192.168.10.2

DNS1=192.168.10.2


2.主机信息配置

/etc/hosts

192.168.10.10 k8s1 192.168.10.11 k8s2 192.168.10.12 k8s3

echo -e "192.168.10.10 k8s1\n192.168.10.11 k8s2\n192.168.10.12 k8s3" >> /etc/hosts

主机名称

/etc/hostname

echo "k8s1" >/etc/hostname

hostname k8s1

su -


关闭selinux

关闭 SELinux,否则后续 K8S 挂载目录时可能报错 Permission denied

cat /etc/selinux/config

SELINUX=disabled

setenforce 0

sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

关闭防火墙

systemctl stop firewalld systemctl disable firewalld


关闭swap内存

如果开启了 swap 分区,kubelet 会启动失败(可以通过将参数 --fail-swap-on 设置为 false 来忽略 swap on),故需要在每台机器上关闭 swap 分区:

swapoff -a

sed -i '/swap/d' /etc/fstab

# swapon -va //启用Swap分区

sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab


关闭 dnsmasq

linux 系统开启了 dnsmasq 后(如 GUI 环境),将系统 DNS Server 设置为 127.0.0.1,这 会导致 docker 容器无法解析域名,需要关闭它:

service dnsmasq stop

systemctl disable dnsmasq


调整内核参数

cat < /etc/sysctl.d/k8s.conf

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward=1

vm.swappiness=0

vm.overcommit_memory=1

vm.panic_on_oom=0

EOF

sysctl --system


添加 k8s 和 docker 账户

useradd -m k8s

passwd k8s

visudo

%wheel ALL=(ALL) NOPASSWD: ALL

cat /etc/group|grep wheel

gpasswd -a k8s wheel

useradd -m docker

gpasswd -a k8s docker


mkdir -p /etc/docker/

/etc/docker/daemon.json

{ "registry-mirrors": ["https://hub-mirror.c.163.com", "https://doc ker.mirrors.ustc.edu.cn"], "max-concurrent-downloads": 20 }


无密码 ssh 登录其它节点

设置 k8s1 可以无密码登录所有节点的 k8s 和 root 账户:

以k8s账号登录

ssh-keygen -t rsa

ssh-copy-id root@k8s1

ssh-copy-id root@k8s2

ssh-copy-id root@k8s3


将可执行文件路径 /opt/k8s/bin 添加到 PATH 变量中

echo 'PATH=/opt/k8s/bin:$PATH:$HOME/bin:$JAVA_HOME/bin' >>/root/.bashrc

echo 'PATH=/opt/k8s/bin:$PATH:$HOME/bin:$JAVA_HOME/bin' >>~/.bashrc


在每台机器上安装依赖包:

yum install -y epel-release

yum install -y conntrack ipvsadm ipset jq sysstat curl iptables


加载内核模块

modprobe br_netfilter

modprobe ip_vs

设置系统时区

查看当前时区

timedatectl

timedatectl set-timezone Asia/Shanghai

timedatectl set-local-rtc 0

ystemctl restart rsyslog

systemctl restart crond


目录配置

mkdir -p /opt/k8s/bin

chown -R k8s /opt/k8s

mkdir -p /etc/kubernetes/cert

chown -R k8s /etc/kubernetes

mkdir -p /etc/etcd/cert

chown -R k8s /etc/etcd/cert

mkdir -p /var/lib/etcd && chown -R k8s /etc/etcd/cert


检测docker环境脚本

curl https://raw.githubusercontent.com/docker/docker/master/contrib /check-config.sh > check-config.sh


集群环境变量

/opt/k8s/bin/environment.sh

#!/usr/bin/bash

# 生成 EncryptionConfig 所需的加密 key

ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

# 最好使用 当前未用的网段 来定义服务网段和 Pod 网段

# 服务网段,部署前路由不可达,部署后集群内路由可达(kube-proxy 和 ipvs 保证)

SERVICE_CIDR="10.254.0.0/16"

# Pod 网段,建议 /16 段地址,部署前路由不可达,部署后集群内路由可达(flanneld保证)

CLUSTER_CIDR="172.30.0.0/16"

# 服务端口范围 (NodePort Range)

export NODE_PORT_RANGE="8400-9000"

# 集群各机器 IP 数组

export NODE_IPS=(192.168.10.10 192.168.10.11 192.168.10.12)

# 集群各 IP 对应的 主机名数组

export NODE_NAMES=(k8s1 k8s2 k8s3)

# kube-apiserver 节点 IP

export MASTER_IP=192.168.10.10

# kube-apiserver https 地址

export KUBE_APISERVER="https://${MASTER_IP}:6443"

# etcd 集群服务地址列表

export ETCD_ENDPOINTS="https://192.168.10.10:2379,https://192.168.10.11:2379,https://192.168.10.12:2379"

# etcd 集群间通信的 IP 和端口

export ETCD_NODES="k8s1=https://192.168.10.10:2380,k8s2=https://192.168.10.11:2380,k8s3=https://192.168.10.12:2380"

# flanneld 网络配置前缀

export FLANNEL_ETCD_PREFIX="/kubernetes/network"

# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)

export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)

export CLUSTER_DNS_SVC_IP="10.254.0.2"

# 集群 DNS 域名

export CLUSTER_DNS_DOMAIN="cluster.local."

# 将二进制目录 /opt/k8s/bin 加到 PATH 中

export PATH=/opt/k8s/bin:$PATH


分发集群环境变量定义脚本

切换到k8s用户

source environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp environment.sh k8s@${node_ip}:/opt/k8s/bin/

ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"

done


安装 cfssl 工具集

mkdir -p /opt/k8s/cert

chown -R k8s /opt/k8s

cd /opt/ k8s

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64

mv cfssl_linux-amd64 /opt/k8s/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64

mv cfssljson_linux-amd64 /opt/k8s/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64

mv cfssl-certinfo_linux-amd64 /opt/k8s/bin/cfssl-certinfo

chmod +x /opt/k8s/bin/*

export PATH=/opt/k8s/bin:$PATH


创建根证书 (CA)

CA 证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由 它签名

创建配置文件

CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务 端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景

k8s1

cd /opt

cat > ca-config.json <<EOF
{
 "signing": {
   "default": {
   "expiry": "87600h"
 },
 "profiles": {
  "kubernetes": {
   "usages": [
    "signing",
    "key encipherment",
    "server auth",
    "client auth"
    ],
   "expiry": "87600h"
   }
  }
 }
}
EOF

signing :表示该证书可用于签名其它证书,生成的 ca.pem 证书中 CA=TRUE ;

server auth :表示 client 可以用该该证书对 server 提供的证书进行验证;

client auth :表示 server 可以用该该证书对 client 提供的证书进行验证;

创建证书签名请求文件

{
 "CN": "kubernetes",
 "key": {
  "algo": "rsa",
  "size": 2048
  },
 "names": [
 {
  "C": "CN",
  "ST": "BeiJing",
  "L": "BeiJing",
  "O": "k8s",
  "OU": "4Paradigm"
 }
 ]
}

CN: Common Name ,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法;

O: Organization ,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;

生成 CA 证书和私钥

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

ls ca*

分发证书文件

将生成的 CA 证书、秘钥文件、配置文件拷贝到所有节点的 /etc/kubernetes/cert 目录下:

source /opt/k8s/bin/environment.sh # 导入 NODE_IPS 环境变量

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp ca*.pem ca-config.json k8s@${node_ip}:/etc/kubernetes/cert

done


部署 kubectl 命令行工具

kubectl 是 kubernetes 集群的命令行管理工具,本文档介绍安装和配置它的步骤。 kubectl 默认从 ~/.kube/config 文件读取 kube-apiserver 地址、证书、用户名等信 息,如果没有配置,执行 kubectl 命令时可能会出错:

$ kubectl get pods

The connection to the server localhost:8080 was refused - did you spe cify the right host or port?

本文档只需要部署一次,生成的 kubeconfig 文件与机器无关。


下载和分发 kubectl 二进制文件

下载和解压:

kubernetes-client-linux-amd64.tar.gz

tar zxvf kubernetes-client-linux-amd64.tar.gz

分发到所有使用 kubectl 的节点:

# 导入 NODE_IPS 环境变量

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp kubernetes/client/bin/kubectl k8s@${node_ip}:/opt/k8s/bin/

ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"

done

chown -R k8s.k8s /opt*


创建 admin 证书和私钥

kubectl 与 apiserver https 安全端口通信,apiserver 对提供的证书进行认证和授权。 kubectl 作为集群的管理工具,需要被授予最高权限。这里创建具有最高权限的 admin 证书。

创建证书签名请求:

{
 "CN": "admin",
 "hosts": [],
 "key": {
  "algo": "rsa",
  "size": 2048
  },
 "names": [
 {
  "C": "CN",
  "ST": "BeiJing",
  "L": "BeiJing",
  "O": "system:masters",
  "OU": "4Paradigm"
 }
 ]
}

O 为 system:masters ,kube-apiserver 收到该证书后将请求的 Group 设置为 system:masters;

预定义的 ClusterRoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予所有 API的权限;

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;


生成证书和私钥:

cfssl gencert -ca=/etc/kubernetes/cert/ca.pem \

-ca-key=/etc/kubernetes/cert/ca-key.pem \

-config=/etc/kubernetes/cert/ca-config.json \

-profile=kubernetes admin-csr.json | cfssljson -bare admin

ls admin*


创建 kubectl.kubeconfig 文件

kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地 址、CA 证书和自身使用的证书;

source /opt/k8s/bin/environment.sh

# 设置集群参数

kubectl config set-cluster kubernetes \

--certificate-authority=/etc/kubernetes/cert/ca.pem \

--embed-certs=true \

--server=${KUBE_APISERVER} \

--kubeconfig=kubectl.kubeconfig


# 设置客户端认证参数

kubectl config set-credentials admin \

--client-certificate=admin.pem \

--client-key=admin-key.pem \

--embed-certs=true \

--kubeconfig=kubectl.kubeconfig

# 设置上下文参数

kubectl config set-context kubernetes \

--cluster=kubernetes \

--user=admin \

--kubeconfig=kubectl.kubeconfig

# 设置默认上下文

kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig


--certificate-authority :验证 kube-apiserver 证书的根证书;

--client-certificate 、 --client-key :刚生成的 admin 证书和私钥,连 接 kube-apiserver 时使用;

--embed-certs=true :将 ca.pem 和 admin.pem 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径);


分发 kubectl.kubeconfig 文件 分

发到所有使用 kubelet 命令的节点:

导入 NODE_IPS 环境变量

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh k8s@${node_ip} "mkdir -p ~/.kube"

scp kubectl.kubeconfig k8s@${node_ip}:~/.kube/config

ssh root@${node_ip} "mkdir -p ~/.kube"

scp kubectl.kubeconfig root@${node_ip}:~/.kube/config

done

保存到用户的 ~/.kube/config 文件;


部署 etcd 集群

etcd 是基于 Raft 的分布式 key-value 存储系统,由 CoreOS 开发,常用于服务发现、 共享配置以及并发控制(如 leader 选举、分布式锁等)。kubernetes 使用 etcd 存储所 有运行数据。

本文档介绍部署一个三节点高可用 etcd 集群的步骤:

下载和分发 etcd 二进制文件;

创建 etcd 集群各节点的 x509 证书,用于加密客户端(如 etcdctl) 与 etcd 集群、 etcd 集群之间的数据流;

创建 etcd 的 systemd unit 文件,配置服务参数;

检查集群工作状态;


下载和分发 etcd 二进制文件

到 https://github.com/coreos/etcd/releases 页面下载最新版本的发布包:

https://github.com/coreos/etcd/releases/download/v3.3.9/etcd-v3.3.9-linux-amd64.tar.gz

分发二进制文件到集群所有节点:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp etcd-v3.3.9-linux-amd64/etcd* k8s@${node_ip}:/opt/k8s/bin

ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"

done


创建 etcd 证书和私钥

创建证书签名请求:

cat > etcd-csr.json <<EOF
{
 "CN": "etcd",
 "hosts": [
 "127.0.0.1",
 "192.168.10.10",
 "192.168.10.11",
 "192.168.10.12"
 ],
 "key": {
  "algo": "rsa",
  "size": 2048
  },
 "names": [
 {
  "C": "CN",
  "ST": "BeiJing",
  "L": "BeiJing",
  "O": "k8s",
  "OU": "4Paradigm"
 }
 ]
}
EOF

hosts 字段指定授权使用该证书的 etcd 节点 IP 或域名列表,这里将 etcd 集群的三 个节点 IP 都列在其中;

生成证书和私钥:

cfssl gencert -ca=/etc/kubernetes/cert/ca.pem \

-ca-key=/etc/kubernetes/cert/ca-key.pem \

-config=/etc/kubernetes/cert/ca-config.json \

-profile=kubernetes etcd-csr.json | cfssljson -bare etcd


分发生成的证书和私钥到各 etcd 节点:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh root@${node_ip} "mkdir -p /etc/etcd/cert && chown -R k8s /etc/etcd/cert"

scp etcd*.pem k8s@${node_ip}:/etc/etcd/cert/

done


创建 etcd 的 systemd unit 模板文件

source /opt/k8s/bin/environment.sh

cat > etcd.service.template <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
User=k8s
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/opt/k8s/bin/etcd \\
--data-dir=/var/lib/etcd \\
--name=##NODE_NAME## \\
--cert-file=/etc/etcd/cert/etcd.pem \\
--key-file=/etc/etcd/cert/etcd-key.pem \\
--trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
--peer-cert-file=/etc/etcd/cert/etcd.pem \\
--peer-key-file=/etc/etcd/cert/etcd-key.pem \\

--peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
--peer-client-cert-auth \\
--client-cert-auth \\
--listen-peer-urls=https://##NODE_IP##:2380 \\
--initial-advertise-peer-urls=https://##NODE_IP##:2380 \\
--listen-client-urls=https://##NODE_IP##:2379,http://127.0.0.1:2379 \\
--advertise-client-urls=https://##NODE_IP##:2379 \\
--initial-cluster-token=etcd-cluster-0 \\
--initial-cluster=${ETCD_NODES} \\
--initial-cluster-state=new
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF

User :指定以 k8s 账户运行;

WorkingDirectory 、 --data-dir :指定工作目录和数据目录为 /var/lib/etcd ,需在启动服务前创建这个目录;

--name :指定节点名称,当 --initial-cluster-state 值为 new 时, -- 04.部署etcd集群 26 name 的参数值必须位于 --initial-cluster 列表中;

--cert-file 、 --key-file :etcd server 与 client 通信时使用的证书和私钥;

--trusted-ca-file :签名 client 证书的 CA 证书,用于验证 client 证书;

--peer-cert-file 、 --peer-key-file :etcd 与 peer 通信使用的证书和私 钥;

--peer-trusted-ca-file :签名 peer 证书的 CA 证书,用于验证 peer 证书;


为各节点创建和分发 etcd systemd unit 文件

替换模板文件中的变量,为各节点创建 systemd unit 文件:

source /opt/k8s/bin/environment.sh

for (( i=0; i < 3; i++ ));

do

sed -e "s/##NODE_NAME##/${NODE_NAMES[i]}/" -e "s/##NODE_IP##/${NODE_IPS[i]}/" etcd.service.template > etcd-${NODE_IPS[i]}.service;

done

ls *.service


NODE_NAMES 和 NODE_IPS 为相同长度的 bash 数组,分别为节点名称和对应 的 IP;

分发生成的 systemd unit 文件:

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh root@${node_ip} "mkdir -p /var/lib/etcd && chown -R k8s /var/lib/etcd"

scp etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service

done


必须先创建 etcd 数据目录和工作目录;

文件重命名为 etcd.service;

启动 etcd 服务

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd &"

done

etcd 进程首次启动时会等待其它节点的 etcd 加入集群,命令 systemctl start etcd 会卡住一段时间,为正常现象。


检查启动结果

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}" ssh k8s@${node_ip} "systemctl status etcd|grep Active"

done

确保状态为 active (running) ,否则查看日志,确认原因:

journalctl -u etcd

验证服务状态

部署完 etcd 集群后,在任一 etc 节点上执行如下命令:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ETCDCTL_API=3 /opt/k8s/bin/etcdctl \

--endpoints=https://${node_ip}:2379 \

--cacert=/etc/kubernetes/cert/ca.pem \

--cert=/etc/etcd/cert/etcd.pem \

--key=/etc/etcd/cert/etcd-key.pem endpoint health

done

输出均为 healthy 时表示集群服务正常。

如果有异常,需要删除 /var/lib/etcd/* 重新启动etcd服务


部署 flannel 网络

kubernetes 要求集群内各节点(包括 master 节点)能通过 Pod 网段互联互通。flannel 使 用 vxlan 技术为各节点创建一个可以互通的 Pod 网络

flaneel 第一次启动时,从 etcd 获取 Pod 网段信息,为本节点分配一个未使用的 /24 段地址,然后创建 flannedl.1 (也可能是其它名称,如 flannel1 等) 接口。

flannel 将分配的 Pod 网段信息写入 /run/flannel/docker 文件,docker 后续使用这 个文件中的环境变量设置 docker0 网桥。

下载和分发 flanneld 二进制文件

到 https://github.com/coreos/flannel/releases 页面下载最新版本的发布包:

wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz

分发 flanneld 二进制文件到集群所有节点:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp flannel/{flanneld,mk-docker-opts.sh} k8s@${node_ip}:/opt/k8s/bin/

ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"

done


创建 flannel 证书和私钥

flannel 从 etcd 集群存取网段分配信息,而 etcd 集群启用了双向 x509 证书认证,所以 需要为 flanneld 生成证书和私钥。 创建证书签名请求:

cat > flanneld-csr.json <<EOF
{
 "CN": "flanneld",
 "hosts": [],
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
  "C": "CN",
  "ST": "BeiJing",
  "L": "BeiJing",
  "O": "k8s",
  "OU": "4Paradigm"
 }
 ]
}
EOF

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;

生成证书和私钥:

cfssl gencert -ca=/etc/kubernetes/cert/ca.pem \

-ca-key=/etc/kubernetes/cert/ca-key.pem \

-config=/etc/kubernetes/cert/ca-config.json \

-profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld

ls flanneld*pem


将生成的证书和私钥分发到所有节点(master 和 worker):

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh root@${node_ip} "mkdir -p /etc/flanneld/cert && chown -R k8s /etc/flanneld"

scp flanneld*.pem k8s@${node_ip}:/etc/flanneld/cert

done


向 etcd 写入集群 Pod 网段信息

注意:本步骤只需执行一次

source /opt/k8s/bin/environment.sh

etcdctl --endpoints=${ETCD_ENDPOINTS} \

--ca-file=/etc/kubernetes/cert/ca.pem \

--cert-file=/etc/flanneld/cert/flanneld.pem \

--key-file=/etc/flanneld/cert/flanneld-key.pem \

set ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 24,"Backend": {"Type": "vxlan"}}'

{"Network":"172.30.0.0/16", "SubnetLen": 24,"Backend": {"Type": "vxlan"}}

flanneld 当前版本 (v0.10.0) 不支持 etcd v3,故使用 etcd v2 API 写入配置 key 和 网段数据;

写入的 Pod 网段 ${CLUSTER_CIDR} 必须是 /16 段地址,必须与 kube-controllermanager 的 --cluster-cidr 参数值一致;


创建 flanneld 的 systemd unit 文件

source /opt/k8s/bin/environment.sh

export IFACE=ens33

cat > flanneld.service << EOF 
[Unit] 
Description=Flanneld overlay address etcd agent 
After=network.target 
After=network-online.target 
Wants=network-online.target 
After=etcd.service 
Before=docker.service 
[Service] 
Type=notify 
ExecStart=/opt/k8s/bin/flanneld \\
-etcd-cafile=/etc/kubernetes/cert/ca.pem \\
-etcd-certfile=/etc/flanneld/cert/flanneld.pem \\
-etcd-keyfile=/etc/flanneld/cert/flanneld-key.pem \\
-etcd-endpoints=${ETCD_ENDPOINTS} \\
-etcd-prefix=${FLANNEL_ETCD_PREFIX} \\
-iface=${IFACE} 
ExecStartPost=/opt/k8s/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTION S -d /run/flannel/docker 
Restart=on-failure 
[Install] 
WantedBy=multi-user.target 
RequiredBy=docker.service 
EOF


mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网网段信息写入 /run/flannel/docker 文件,后续 docker 启动时使用这个文件中的环境变量配 置 docker0 网桥

flanneld 使用系统缺省路由所在的接口与其它节点通信,对于有多个网络接口(如 内网和公网)的节点,可以用 -iface 参数指定通信接口,如上面的 eth0 接口;

flanneld 运行时需要 root 权限;

分发 flanneld systemd unit 文件到所有节点

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp flanneld.service root@${node_ip}:/etc/systemd/system/

done


启动 flanneld 服务

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh root@${node_ip} "systemctl daemon-reload && systemctl enable flanneld && systemctl restart flanneld"

done


检查启动结果

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh k8s@${node_ip} "systemctl status flanneld|grep Active"

done

确保状态为 active (running) ,否则查看日志,确认原因:

journalctl -u flanneld


检查分配给各 flanneld 的 Pod 网段信息

查看集群 Pod 网段(/16):

source /opt/k8s/bin/environment.sh

etcdctl \

--endpoints=${ETCD_ENDPOINTS} \

--ca-file=/etc/kubernetes/cert/ca.pem \

--cert-file=/etc/flanneld/cert/flanneld.pem \

--key-file=/etc/flanneld/cert/flanneld-key.pem \

get ${FLANNEL_ETCD_PREFIX}/config

{"Network":"172.30.0.0/16", "SubnetLen": 24,"Backend": {"Type": "vxlan"}}

查看已分配的 Pod 子网段列表(/24):

source /opt/k8s/bin/environment.sh

etcdctl \

--endpoints=${ETCD_ENDPOINTS} \

--ca-file=/etc/kubernetes/cert/ca.pem \

--cert-file=/etc/flanneld/cert/flanneld.pem \

--key-file=/etc/flanneld/cert/flanneld-key.pem \

ls ${FLANNEL_ETCD_PREFIX}/subnets

/kubernetes/network/subnets/172.30.100.0-24

/kubernetes/network/subnets/172.30.48.0-24

/kubernetes/network/subnets/172.30.4.0-2


查看某一 Pod 网段对应的节点 IP 和 flannel 接口地址:

source /opt/k8s/bin/environment.sh

etcdctl \

--endpoints=${ETCD_ENDPOINTS} \

--ca-file=/etc/kubernetes/cert/ca.pem \

--cert-file=/etc/flanneld/cert/flanneld.pem \

--key-file=/etc/flanneld/cert/flanneld-key.pem \

get ${FLANNEL_ETCD_PREFIX}/subnets/172.30.48.0-24

{"PublicIP":"192.168.10.10","BackendType":"vxlan","BackendData":{"VtepMAC":"92:a3:f6:f2:9f:e1"}}

验证各节点能通过 Pod 网段互通

在各节点上部署 flannel 后,检查是否创建了 flannel 接口(名称可能为 flannel0、 flannel.0、flannel.1 等):

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh ${node_ip} "/usr/sbin/ip addr show flannel.1|grep -w inet"

done

在各节点上 ping 所有 flannel 接口 IP,确保能通:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

ssh ${node_ip} "ping -c 1 172.30.100.0"

ssh ${node_ip} "ping -c 1 172.30.48.0"

ssh ${node_ip} "ping -c 1 172.30.4.0"

done


部署 master 节点

kubernetes master 节点运行如下组件:

kube-apiserver

kube-scheduler

kube-controller-manager

这 3 个组件均可以以集群模式运行,通过 leader 选举产生一个工作进程,其它进程处于 阻塞模式

下载最新版本的二进制文件

tar -xzvf kubernetes-server-linux-amd64.tar.gz

cd kubernetes

tar -xzvf kubernetes-src.tar.gz

将二进制文件拷贝到所有 master 节点:

source /opt/k8s/bin/environment.sh

for node_ip in ${NODE_IPS[@]}

do

echo ">>> ${node_ip}"

scp server/bin/* k8s@${node_ip}:/opt/k8s/bin/

ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"

done


部署 kube-apiserver 组件

本文档讲解部署一个单 master 的部署,对应的节点 IP 为环境变量 ${MASTER_IP}。

创建 kubernetes 证书和私钥

创建证书签名请求:

source /opt/k8s/bin/environment.sh

cat > kubernetes-csr.json <

{

"CN": "kubernetes",

"hosts": [

"127.0.0.1",

"${MASTER_IP}",

"${CLUSTER_KUBERNETES_SVC_IP}",

"kubernetes",

"kubernetes.default",

"kubernetes.default.svc",

"kubernetes.default.svc.cluster",

"kubernetes.default.svc.cluster.local"

],

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "CN",

"ST": "BeiJing",

"L": "BeiJing",

"O": "k8s",

"OU": "4Paradigm"

}

]

}

EOF


hosts 字段指定授权使用该证书的 IP 或域名列表,这里列出了 apiserver 节点 IP、 kubernetes 服务 IP 和域名;

域名最后字符不能是 . (如不能为 kubernetes.default.svc.cluster.local. ),否则解析时失败,提示: x509: cannot parse dnsName "kubernetes.default.svc.cluster.local." ;

如果使用非 cluster.local 域名,如 opsnull.com ,则需要修改域名列表中 的最后两个域名 为: kubernetes.default.svc.opsnull 、 kubernetes.default.svc.opsnull .com

kubernetes 服务 IP 是 apiserver 自动创建的,一般是 --service-cluster-iprange 参数指定的网段的第一个IP,后续可以通过如下命令获取:

kubectl get svc kubernetes


生成证书和私钥:

cfssl gencert -ca=/etc/kubernetes/cert/ca.pem \

-ca-key=/etc/kubernetes/cert/ca-key.pem \

-config=/etc/kubernetes/cert/ca-config.json \

-profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes

ls kubernetes*


将生成的证书和私钥文件拷贝到 master 节点:

source /opt/k8s/bin/environment.sh

ssh root@${MASTER_IP} "mkdir -p /etc/kubernetes/cert/ && sudo chown - R k8s /etc/kubernetes/cert/"

scp kubernetes*.pem k8s@${MASTER_IP}:/etc/kubernetes/cert/

k8s 账户可以读写 /etc/kubernetes/cert/ 目录;

创建加密配置文件

source /opt/k8s/bin/environment.sh

cat > encryption-config.yaml <

kind: EncryptionConfig

apiVersion: v1

resources:

- resources:

- secrets

providers:

- aescbc:

keys:

- name: key1

secret: ${ENCRYPTION_KEY}

- identity: {}

EOF


将加密配置文件拷贝到 master 节点的 /etc/kubernetes 目录下:

source /opt/k8s/bin/environment.sh

scp encryption-config.yaml root@${MASTER_IP}:/etc/kubernetes/

创建和分发 kube-apiserver systemd unit 文件

source /opt/k8s/bin/environment.sh

cat > kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart=/opt/k8s/bin/kube-apiserver \\
--enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
--anonymous-auth=false \\
--experimental-encryption-provider-config=/etc/kubernetes/encryption-config.yaml \\
--advertise-address=${MASTER_IP} \\
--bind-address=${MASTER_IP} \\
--insecure-port=0 \\
--authorization-mode=Node,RBAC \\
--runtime-config=api/all \\
--enable-bootstrap-token-auth \\
--service-cluster-ip-range=${SERVICE_CIDR} \\
--service-node-port-range=${NODE_PORT_RANGE} \\
--tls-cert-file=/etc/kubernetes/cert/kubernetes.pem \\
--tls-private-key-file=/etc/kubernetes/cert/kubernetes-key.pem \\
--client-ca-file=/etc/kubernetes/cert/ca.pem \\
--kubelet-client-certificate=/etc/kubernetes/cert/kubernetes.pem \\
--kubelet-client-key=/etc/kubernetes/cert/kubernetes-key.pem \\
--service-account-key-file=/etc/kubernetes/cert/ca-key.pem \\
--etcd-cafile=/etc/kubernetes/cert/ca.pem \\
--etcd-certfile=/etc/kubernetes/cert/kubernetes.pem \\
--etcd-keyfile=/etc/kubernetes/cert/kubernetes-key.pem \\
--etcd-servers=${ETCD_ENDPOINTS} \\
--enable-swagger-ui=true \\
--allow-privileged=true \\
--apiserver-count=3 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/log/kube-apiserver-audit.log \\
--event-ttl=1h \\
--alsologtostderr=true \\
--logtostderr=false \\
--log-dir=/var/log/kubernetes \\
--v=2
Restart=on-failure

RestartSec=5
Type=notify
User=k8s
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF

--experimental-encryption-provider-config :启用加密特性;

--authorization-mode=Node,RBAC : 开启 Node 和 RBAC 授权模式,拒绝未授 权的请求;

--enable-admission-plugins :启用 ServiceAccount 和 NodeRestriction ;

--service-account-key-file :签名 ServiceAccount Token 的公钥文件, kube-controller-manager 的 --service-account-private-key-file 指定私钥 文件,两者配对使用;

--tls-*-file :指定 apiserver 使用的证书、私钥和 CA 文件。 --client-cafile 用于验证 client (kue-controller-manager、kube-scheduler、kubelet、kubeproxy 等)请求所带的证书;

--kubelet-client-certificate 、 --kubelet-client-key :如果指定,则使 用 https 访问 kubelet APIs;需要为证书对应的用户(上面 kubernetes*.pem 证书的 用户为 kubernetes) 用户定义 RBAC 规则,否则访问 kubelet API 时提示未授权;

--bind-address : 不能为 127.0.0.1 ,否则外界不能访问它的安全端口 6443;

--insecure-port=0 :关闭监听非安全端口(8080);

--service-cluster-ip-range : 指定 Service Cluster IP 地址段;

--service-node-port-range : 指定 NodePort 的端口范围;

--runtime-config=api/all=true : 启用所有版本的 APIs,如 autoscaling/v2alpha1;

--enable-bootstrap-token-auth :启用 kubelet bootstrap 的 token 认证;

--apiserver-count=3 :指定集群运行模式,多台 kube-apiserver 会通过 leader 选举产生一个工作节点,其它节点处于阻塞状态; User=k8s :使用 k8s 账户运行


分发 systemd uint 文件到 master 节点:

source /opt/k8s/bin/environment.sh

scp kube-apiserver.service root@${MASTER_IP}:/etc/systemd/system/

ssh root@${MASTER_IP} "mkdir -p /var/log/kubernetes && chown -R k8s /var/log/kubernetes"

必须先创建日志目录;

授予 kubernetes 证书访问 kubelet API 的权限

在执行 kubectl exec、run、logs 等命令时,apiserver 会转发到 kubelet。这里定义 RBAC 规则,授权 apiserver 调用 kubelet API。

kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes

启动 kube-apiserver 服务

ssh root@${MASTER_IP} "systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver"

检查 kube-apiserver 运行状态

ssh root@${MASTER_IP} "systemctl status kube-apiserver |grep 'Active: '"

确保状态为 active (running) ,否则到 master 节点查看日志,确认原因:

$ journalctl -u kube-apiserver

打印 kube-apiserver 写入 etcd 的数据

source /opt/k8s/bin/environment.sh

ETCDCTL_API=3 etcdctl \

--endpoints=${ETCD_ENDPOINTS} \

--cacert=/etc/kubernetes/cert/ca.pem \

--cert=/etc/etcd/cert/etcd.pem \

--key=/etc/etcd/cert/etcd-key.pem \

get /registry/ --prefix --keys-only

检查集群信息

kubectl cluster-info




Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表