Fork me on GitHub

二进制部署k8s1.12

二进制部署k8s

1.介绍

  • k8s是谷歌开源容器集群管理系统,它可以应用于程序部署扩展和管理,它提供了容器编排,资源调度,弹性伸缩,部署管理服务发现等一系列功能。

2.k8s的集群架构与组件

主节点Master运行着:API Server, scheduler, controller-manager三个节点
工作节点Node运行着:kubelet, kube-proxy
  • Master组件
kube-apiserver
	集群统一入口,各组件协调者,以restfulAPI提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后提交给ETCD存储。

kube-controller-manager
	处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager就是负责管理这些控制器的
kube-scheduler
	根据调度算法为新的创建Pod选择一个Node节点,可以任意部署,可以部署在一个节点上,也可以部署在不同节点上
etcd
	分布式键值存储系统,用于保存集群状态数据,比如pod service等对象信息
  • Node组件
kubelet
	它是Master在Node节点上Agent,管理本机运行容器生命周期,比如:创建容器,Pod挂载卷,下载secret,获取若能国企和节点状态工作,kubelet将每个Pod转换成一组容器
kube-proxy
	在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡
docker  rocker
	容器引擎,运行容器

3.K8s核心概念

  • Pod部署应用的最小单元

    它是最小部署单元,它一组容器的集合,而且一个Pod中的可能有多个容器,容器之间网络是共享(当一个容器监听8080端口,其他的容器也能看见,并且通过k8s数据卷也能实现容器之间的数据的共享),而它们文件系统是隔离的。Pod是短暂的,当你触发服务更新或发布,那么之前pod就会销毁。

  • Controllers控制器

    1.ReplicaSet: 确保预期的Pod副本数量

    2.Deployment:用于无状态应用部署。

    3.StatefulSet:用于有状态应用部署

    4.DaemonSet:确保所有Node运行同一个Pod

    5.Job:一次性任务。

    6.Cronjob: 定时任务。

  • Service服务转发

    1.防止Pod失去联系,定义一组Pod的访问策略

  • Label 标签

    标签,附加在某个资源上,用于关联对象,查询和筛选。

  • Namespace

    命名空间,将对象逻辑上隔离

什么是无状态应用和有状态的应用??
无状态:deployment
  - 认为所有pod都是一样的,不具备与其他实例有不同的关系。
  - 没有顺序的要求。
  - 不用考虑再哪个Node运行。
  - 随意扩容缩容。

有状态:SatefulSet
  - 集群节点之间的关系。
  - 数据不完全一致。
  - 实例之间不对等的关系。
  - 依靠外部存储的应用。
  - 通过dns维持身份
  像MySQl主从,Zookepeer

4.K8s部署前言:

  • 官方提供的三种部署方式:

    • minikube

      Minikube是一个工具,可以在本地快速运行一个单点Kubernetes,仅用于尝试kubernetes或日常开发的用户。

      网址

    • kubeadm

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

      网址

    • 二进制

      手动部署每个组件

      网址

  • 软件版本:

    软件名称 版本号
    Linux操作系统 CentOs7.5_x64 +
    Kubemetes 1.13
    Etcd 3.+
    Docker 18.+
    Flannel 0.10
  • 角色对应关系:

角色 部署IP 组件
k8s-master01 192.168.48.128 kube-apiserver,kube-controller-manager,kube-scheduler,etcd
k8s-node01 192.168.48.130 kubelet,kube-proxy,docker,flannel,etcd
k8s-node02 192.168.48.131 kubelet, kube-proxy,docker,flannel,etcd
  • 部署架构图:

5.前续工作:

  • 关闭各所有机器SELINUX和防火墙

    vi /etc/selinux/config 
    SELINUX=disabled
    setenforce 0
    systemctl stop firewalld
    
    # 验证:iptables -vnL
    
  • 修改主机名

    # 192.168.48.128 改成 k8s-master01
    vi /etc/hostname
    hostname k8s-master01
    exit退出终端再进入。
    
    以相同方式更改node01和node02的名字:
    # 192.168.48.130 改成 k8s-node01
    # 192.168.48.131 改成 k8s-node02
    

6.HTTPS证书构建

  • 因为apiServer 与 kubelet之间通信是https, etcd(数据库)与 Flannel之间通信也是https

  • 自签SSL证书:我们需要构建2套证书,ca证书,和api-server证书。【ca.pem,server.pem代表证书, server-key代表私钥】

    apiserver 加 ca-key.pem
    
  • 为etcd生成证书

    # 时间同步:(所有机器都同步)
    	下载ntpdate: yum install ntpdate
    	更新最新时间: ntpdate time.windows.com
    # 首先需要下载cfssl工具
    	执行脚本:[/root/k8s/etcd-cert:] bash cfssl.sh
    # 生成ca:# 执行下面命令会生成ca-config.json,ca-csr.json两个文件。
    cat > ca-config.json <<EOF
    {
      "signing": {
        "default": {
          "expiry": "87600h"
        },
        "profiles": {
          "www": {
             "expiry": "87600h",
             "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ]
          }
        }
      }
    }
    EOF
    
    cat > ca-csr.json <<EOF
    {
        "CN": "etcd CA",
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "L": "Beijing",
                "ST": "Beijing"
            }
        ]
    }
    EOF
    # 生成根证书:initca 初始化ca-csr.json 配置文件
    cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
    
    # 生成etcd域名证书:配置部署etcd节点所有的IP
    cat > server-csr.json <<EOF
    {
        "CN": "etcd",
        "hosts": [
        "192.168.48.128",
        "192.168.48.130",
        "192.168.48.131"
        ],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "L": "BeiJing",
                "ST": "BeiJing"
            }
        ]
    }
    EOF
    # 请求ca颁发证书:
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
    # 此时会生成:server.pem 和 server-key.pem 而etcd使用这2个证书即可
    

7.ETCD数据库集群部署

  • 准备工作
[root@k8s-master01 ~]# mkdir soft
[root@k8s-master01 ~]# cd soft/
# 解压之前下载好的etcd包:etcd-v3.3.10-linux-amd64.tar.gz
tar -zxvf etcd-v3.3.10-linux-amd64.tar.gz
[root@k8s-master01 soft]# cd etcd-v3.3.10-linux-amd64
[root@k8s-master01 etcd-v3.3.10-linux-amd64]# ls
Documentation  etcd  etcdctl  README-etcdctl.md  README.md  READMEv2-etcdctl.md
# etcd 启动etcd服务
# etcdctl 管理etcd客户端命令
# 创建etcd管理目录:
mkdir /opt/etcd/{cfg,bin,ssl} -p
# 将 etcd,etcdctl 移动到 /opt/etcd/bin
mv etcd etcdctl /opt/etcd/bin/
  • etcd部署脚本(一般生产环境使用5台,但最小使用3台):
写etcd.sh脚本:
#!/bin/bash
# example: ./etcd.sh etcd01 192.168.1.10 etcd02=https://192.168.1.11:2380,etcd03=https://192.168.1.12:2380

ETCD_NAME=$1
ETCD_IP=$2
ETCD_CLUSTER=$3
# 工作目录定义
WORK_DIR=/opt/etcd
# 生成etcd配置文件
# Member中 2380端口设置集群之间通信,2379是数据传输端口
# Clustering 集群配置信息


cat <<EOF >$WORK_DIR/cfg/etcd
#[Member]
ETCD_NAME="${ETCD_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379"

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://${ETCD_IP}:2380,${ETCD_CLUSTER}"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
# 配置证书选项
cat <<EOF >/usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=${WORK_DIR}/cfg/etcd
ExecStart=${WORK_DIR}/bin/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=${WORK_DIR}/ssl/server.pem \
--key-file=${WORK_DIR}/ssl/server-key.pem \
--peer-cert-file=${WORK_DIR}/ssl/server.pem \
--peer-key-file=${WORK_DIR}/ssl/server-key.pem \
--trusted-ca-file=${WORK_DIR}/ssl/ca.pem \
--peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
# 启动命令
systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd

# 赋予执行权限
chmod +x etcd.sh
  • 使用方式
./etcd.sh 当前节点名 当前节点ip 节点2的名=https://节点2的ip:2380,节点3的名=https://节点2的ip:2380

#示例:
./etcd.sh etcd01 192.168.48.128 etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380
# 执行脚本:
./etcd.sh etcd01 192.168.48.128 etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380
  • 查看,检查配置文件:
#############################1#############################
cat /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd01"# 当前节点名字
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.48.128:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.48.128:2379"

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.48.128:2380"# 2380端口设置集群之间通信
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.48.128:2379"# 2379是数据传输端口
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.48.128:2380,etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380"# 集群中节点
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"# token认证
ETCD_INITIAL_CLUSTER_STATE="new"# 代表新的集群
###############################2############################
cat /usr/lib/systemd/system/etcd.service 
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd
ExecStart=/opt/etcd/bin/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/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --peer-cert-file=/opt/etcd/ssl/server.pem --peer-key-file=/opt/etcd/ssl/server-key.pem --trusted-ca-file=/opt/etcd/ssl/ca.pem --peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
  • 将证书拷贝到/opt/etcd/ssl
cp ~/k8s/etcd-cert/{ca,server-key,server}.pem /opt/etcd/ssl

ls /opt/etcd/ssl 查看证书
ca.pem  server-key.pem  server.pem
  • 启动etcd
systemctl start etcd
  • 查看启动日志:
tail /var/log/messages -f
  • 将etcd配置拷贝其他2台机器上
scp -r /opt/etcd/ root@192.168.48.130:/opt/
scp -r /opt/etcd/ root@192.168.48.131:/opt/
  • 将etcd.service拷贝到其他2台机器
scp /usr/lib/systemd/system/etcd.service root@192.168.48.130:/usr/lib/systemd/system
scp /usr/lib/systemd/system/etcd.service root@192.168.48.131:/usr/lib/systemd/system
  • 修改192.168.48.130, 192.168.48.131配置文件
vim /opt/etcd/cfg/etcd

修改ETCD_NAME,ETCD_LISTEN_PEER_URLS, ETCD_LISTEN_CLIENT_URLS,ETCD_INITIAL_ADVERTISE_PEER_URLS,ETCD_ADVERTISE_CLIENT_URLS
  • daemon-reload 和 启动
systemctl daemon-reload
systemctl start etcd
  • 验证etcd集群状态
/opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379"  cluster-health
  • 下面结果显示代表集群健康:
member 3f3868c5ec7337c4 is healthy: got healthy result from https://192.168.48.128:2379
member c3e65c73ad3cc87a is healthy: got healthy result from https://192.168.48.131:2379
member c4f45bf163b686e6 is healthy: got healthy result from https://192.168.48.130:2379
cluster is healthy

8.node安装docker

  • yum安装必要的组件

    yum install -y yum-utils device-mapper-persistent-data lvm2
    
  • 添加软件源信息

    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  • 安装docker

    yum -y install docker-ce
    
  • 启动docker

    systemctl start docker
    
  • daocloud配置docker加速器

    curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
    
  • 重启docker

    systemctl restart docker
    

9.Kubernetes网络模型(CNI)

  • CNI容器网络接口。Kubernetes网络模型设计基本要求:

    1. 一个Pod一个ip
    2. 每个Pod独立IP,Pod内所有容器共享网络(同一个IP)
    3. 所有容器都可以与所有其他容器通信
    4.所有节点都可以与所有容器通信
    

    而实现上面要求实现方案为:隧道方案或路由方案,相比来说路由方案网络开销很小,常用实现组件:flannel和calico.flannel适用于小规模的,它局限于统一局域网之内,它对网络适应能力强。Calico基于BGP协议进行通信,它有很多网络通信是不支持的。大规模的适合calico,小规模适合flannel。

10.部署Kubernetes网络-Flannel

master节点

  • 为k8s分配子网,在Master主机上设置:

    /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379"  set /coreos.com/network/config '{"Network":"172.17.0.0/16", "Backend": {"Type": "vxlan"}}'
    

node节点

  • node节点创建工作目录

    mkdir /opt/kubernetes/{bin,cfg,ssl} -p
    
  • 下载flannel二进制包

    flannel-v0.10.0-linux-amd64.tar.gz
    
  • 解压flannel包

    tar zxvf flannel-v0.10.0-linux-amd64.tar.gz
    
  • 将解压生成的flanneld 和 mk-docker-opts.sh移动到/opt/kubernetes/bin/

    mv flanneld mk-docker-opts.sh /opt/kubernetes/bin/
    
  • shell安装 flannel

    # 生成flannel配置文件,指定使用etcd地址
    cat <<EOF >/opt/kubernetes/cfg/flanneld
    
    FLANNEL_OPTIONS="--etcd-endpoints=${ETCD_ENDPOINTS} \
    -etcd-cafile=/opt/etcd/ssl/ca.pem \
    -etcd-certfile=/opt/etcd/ssl/server.pem \
    -etcd-keyfile=/opt/etcd/ssl/server-key.pem"
    
    EOF
    
    # 生成flannel.service配置文件
    cat <<EOF >/usr/lib/systemd/system/flanneld.service
    [Unit]
    Description=Flanneld overlay address etcd agent
    After=network-online.target network.target
    Before=docker.service
    
    [Service]
    Type=notify
    EnvironmentFile=/opt/kubernetes/cfg/flanneld
    ExecStart=/opt/kubernetes/bin/flanneld --ip-masq \$FLANNEL_OPTIONS
    ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
    
    EOF
    
    # 修改docker配置文件
    
    cat <<EOF >/usr/lib/systemd/system/docker.service
    
    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network-online.target firewalld.service
    Wants=network-online.target
    
    [Service]
    Type=notify
    EnvironmentFile=/run/flannel/subnet.env
    ExecStart=/usr/bin/dockerd \$DOCKER_NETWORK_OPTIONS
    ExecReload=/bin/kill -s HUP \$MAINPID
    LimitNOFILE=infinity
    LimitNPROC=infinity
    LimitCORE=infinity
    TimeoutStartSec=0
    Delegate=yes
    KillMode=process
    Restart=on-failure
    StartLimitBurst=3
    StartLimitInterval=60s
    
    [Install]
    WantedBy=multi-user.target
    
    EOF
    
    systemctl daemon-reload
    systemctl enable flanneld
    systemctl restart flanneld
    systemctl restart docker
    
    
    
    
  • 执行脚本,后面参数指定etcd的地址

    ./flannel.sh https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379
    
  • 查看flanneld配置是否生效

    cat /opt/kubernetes/cfg/flanneld
    
  • 查看flannel.service配置

    cat /usr/lib/systemd/system/flanneld.service 
    
  • 启动flannel

    systemctl start flanneld
    
  • 查看启动状态

    ps -ef | grep flannel
    
  • 查看启动失败日志

    tail /var/log/messages -f
    
  • 重启docker,看是否引用flannel分配的子网

    [root@k8s-node02 ~]# systemctl restart docker
    [root@k8s-node02 ~]# ps -ef | grep docker
    root       2613      1  1 23:25 ?        00:00:00 /usr/bin/dockerd --bip=172.17.44.1/24 --ip-masq=false --mtu=1450
    root       2753   1351  0 23:26 pts/0    00:00:00 grep --color=auto docker
    
    # --bip看到引用的子网了,也可以用ifconfig查看docker0的ip
    

拷贝其他node节点拷贝

scp -r /opt/kubernetes/ root@192.168.48.131:/opt/
scp /usr/lib/systemd/system/{flanneld,docker}.service root@192.168.48.131:/usr/lib/systemd/system
# 启动flannel
systemctl start flannel
# 重启docker
systemctl restart docker

验证:

在node1运行容器并进入:docker run -it busybox
ifconfig查看容器ip
在node2 去 ping 该ip看是否通

在node1与node2的容器内互相ping
  • etcd查看运行node节点
[root@k8s-master01 k8s]# /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379"  get /coreos.com/network/subnets
/coreos.com/network/subnets: is a directory
[root@k8s-master01 k8s]# /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379"  ls /coreos.com/network/subnets/
/coreos.com/network/subnets/172.17.68.0-24
/coreos.com/network/subnets/172.17.44.0-24
[root@k8s-master01 k8s]# /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379"  get /coreos.com/network/subnets/172.17.68.0-24
{"PublicIP":"192.168.48.130","BackendType":"vxlan","BackendData":{"VtepMAC":"5a:5f:22:12:e8:62"}}

11.k8s Master组件部署

11.1api-server

  • 官网下载kubernetes包,上传master服务端
kubernetes-server-linux-amd64.tar.gz  1.13版本
  • 解压kubernetes-server包
tar zxvf kubernetes-server-linux-amd64.tar.gz
  • master创建kubernetes管理目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl}
  • cd到解压后kubernetes/server/bin中
cd kubernetes/server/bin
  • 将kube-apiserver kube-controller-manager kube-scheduler 拷贝到 /opt/kubernetes/bin下
cp kube-apiserver kube-controller-manager kube-scheduler /opt/kubernetes/bin/
  • 编写apiserver.sh脚本
#!/bin/bash

MASTER_ADDRESS=$1# 指定当前apiserver地址
ETCD_SERVERS=$2# 指定etcd地址
# 生成apiserver配置文件
cat <<EOF >/opt/kubernetes/cfg/kube-apiserver

KUBE_APISERVER_OPTS="--logtostderr=false \\
--log-dir=/opt/kubernetes/logs \\# 日志目录
--v=4 \\#日志级别
--etcd-servers=${ETCD_SERVERS} \\# etcd-server地址
--bind-address=${MASTER_ADDRESS} \\#绑定ip地址
--secure-port=6443 \\#apiserver 地址
--advertise-address=${MASTER_ADDRESS} \\# 集群通告地址
--allow-privileged=true \\# 授权是否允许(容器层面的)
--service-cluster-ip-range=10.0.0.0/24 \\# 指定负载均衡ip
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\# 启用准入插件
--authorization-mode=RBAC,Node \\#认证模式
--kubelet-https=true \\# 启用https
--enable-bootstrap-token-auth \\#认证用的
--token-auth-file=/opt/kubernetes/cfg/token.csv \\#token文件
--service-node-port-range=30000-50000 \\# 端口范围
--tls-cert-file=/opt/kubernetes/ssl/server.pem  \\#配置apiserver证书路径
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \\
--client-ca-file=/opt/kubernetes/ssl/ca.pem \\#配置ca证书
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--etcd-cafile=/opt/etcd/ssl/ca.pem \\# etcd的ca证书
--etcd-certfile=/opt/etcd/ssl/server.pem \\
--etcd-keyfile=/opt/etcd/ssl/server-key.pem"

EOF
# 生成 apiserver.service 配置文件
cat <<EOF >/usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-apiserver
systemctl restart kube-apiserver
  • 创建日志目录
mkdir /opt/kubernetes/logs
  • 启动apiserver.sh脚本
./apiserver.sh 当前master地址 etcd地址
./apiserver.sh 192.168.48.128 https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379
  • 查看apiserver配置文件是否生效
cat /opt/kubernetes/cfg/kube-apiserver 
  • k8s证书生成
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

cat > ca-csr.json <<EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing",
      	    "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

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

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

cat > server-csr.json <<EOF
{
    "CN": "kubernetes",
    "hosts": [
      "10.0.0.1",
      "127.0.0.1",
      "192.168.48.128",# 这里写master的ip , LB的ip,也可多写几个ip备用,node节点可以不用写
      "192.168.48.129",
      "192.168.48.132",
      "192.168.48.133",
      "192.168.48.134",
      "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

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

#-----------------------
# 访问k8s集群时候会用到证书
cat > 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

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin

#-----------------------
# kube-proxy证书
cat > 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

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

  • 执行脚本
bash k8s-cert.sh
  • 将 ca.pem server.pem server-key.pem 放到 /opt/kubernetes/ssl/
cp ca-key.pem ca.pem server.pem server-key.pem /opt/kubernetes/ssl/
  • 生成token
BOOTSTRAP_TOKEN=0fb61c46f8991b718eb38d27b605b008

cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
  • 查看token.csv
[root@k8s-master01 k8s-cert]# cat token.csv 
0fb61c46f8991b718eb38d27b605b008,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
      # token的ip				标识用户         #用户组    # 加入k8s角色		
  • 移动token.csv 到/opt/kubernetes/cfg/
mv token.csv /opt/kubernetes/cfg/
  • 启动apiserver
systemctl start kube-apiserver
  • 查看是否启动
ps -ef | grep kube-apiserver
  • 若没有正常启动采用手动启动排查问题
source /opt/kubernetes/cfg/kube-apiserver
/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS

11.2controller-manager

  • api-server 默认本地监听8080和6443,通过下列指令查看端口

    netstat -antp | grep 8080
    netstat -antp | grep 6443
    
  • 编写脚本controller-manager.sh

#!/bin/bash
# api-server的地址
MASTER_ADDRESS=$1

cat <<EOF >/opt/kubernetes/cfg/kube-controller-manager


KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \\
--v=4 \\
--master=${MASTER_ADDRESS}:8080 \\# 本地启动ip端口
--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/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--experimental-cluster-signing-duration=87600h0m0s"

EOF

cat <<EOF >/usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl restart kube-controller-manager

  • 运行脚本
./controller-manager.sh 本地ip
./controller-manager.sh 127.0.0.1
  • 验证
cat /opt/kubernetes/cfg/kube-controller-manager

KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \# 本地启动ip端
--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/kubernetes/ssl/ca.pem \# 证书签名
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \
--experimental-cluster-signing-duration=87600h0m0s" #为k8s办法证书时间
  • 也可将日志文件修改指定文件:
vi /opt/kubernetes/cfg/kube-controller-manager
# 修改 --logtostderr=false
# 修改 --log-dir=指定日志目录,需之前创建好

11.3 scheduler

  • 编写脚本scheduler.sh
#!/bin/bash

MASTER_ADDRESS=$1

cat <<EOF >/opt/kubernetes/cfg/kube-scheduler

KUBE_SCHEDULER_OPTS="--logtostderr=true \\
--v=4 \\
--master=${MASTER_ADDRESS}:8080 \\
--leader-elect"

EOF

cat <<EOF >/usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-scheduler
systemctl restart kube-scheduler

  • 运行脚本
./scheduler.sh 本地ip
./scheduler.sh 127.0.0.1
  • 验证
[root@k8s-master01 k8s]# cat /opt/kubernetes/cfg/kube-scheduler 

KUBE_SCHEDULER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \
--leader-elect"

11.4查看集群状态

  • 将管理k8s集群的工具kubectl拷贝到/usr/bin下方便使用
cp /root/soft/kubernetes/server/bin/kubectl /usr/bin/
  • 查看etcd集群,scheduler,controller-manager状态
kubectl get cs

NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"} 

12.k8s 中node部署

  • 在Master中,将之前生成token.csv中定义kubelet-bootstrap用户绑定到系统集群角色
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

​ 删除角色名字: kubectl delete clusterrolebinding kubelet-bootstrap [clusterrolebinding kubelet-bootstrap为角色名字]

  • Master创建kubeconfig.sh,生成证书,它用于存放连接apiserver的信息
APISERVER=$1# 指定apiserver的ip
SSL_DIR=$2# ssl证书目录
BOOTSTRAP_TOKEN=0fb61c46f8991b718eb38d27b605b008
# 创建kubelet bootstrapping kubeconfig 
export KUBE_APISERVER="https://$APISERVER:6443"

# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=$SSL_DIR/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=$SSL_DIR/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig

kubectl config set-credentials kube-proxy \
  --client-certificate=$SSL_DIR/kube-proxy.pem \
  --client-key=$SSL_DIR/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
  • 运行脚本
bash kubeconfig.sh apiserver的ip ssl证书目录


bash kubeconfig.sh 192.168.48.128 /root/k8s/k8s-cert
  • 此时生成有2个带kubeconfig后缀文件
kube-proxy.kubeconfig
bootstrap.kubeconfig
  • 拷贝kube-proxy.kubeconfig, bootstrap.kubeconfig到node节点上
scp kube-proxy.kubeconfig bootstrap.kubeconfig root@192.168.48.130:/opt/kubernetes/cfg/

scp kube-proxy.kubeconfig bootstrap.kubeconfig root@192.168.48.131:/opt/kubernetes/cfg/
  • Master中 /root/soft/kubernetes/server/bin/拷贝kubelet,kube-proxy拷贝到node节点上
scp kubelet kube-proxy root@192.168.48.130:/opt/kubernetes/bin
scp kubelet kube-proxy root@192.168.48.131:/opt/kubernetes/bin

kubelet.sh

  • node编写脚本kubelet.sh
#!/bin/bash

NODE_ADDRESS=$1# 指定当前节点ip
DNS_SERVER_IP=${2:-"10.0.0.2"}#部署dns使用ip
# kubelet配置文件
cat <<EOF >/opt/kubernetes/cfg/kubelet

KUBELET_OPTS="--logtostderr=false \\
--log-dir=/opt/kubernetes/logs \\
--v=4 \\
--address=${NODE_ADDRESS} \\
--hostname-override=${NODE_ADDRESS} \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet.config \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"

EOF
# kubelet.config 配置文件
cat <<EOF >/opt/kubernetes/cfg/kubelet.config

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: ${NODE_ADDRESS}
port: 10250
cgroupDriver: cgroupfs
clusterDNS:
- ${DNS_SERVER_IP}
clusterDomain: cluster.local.
failSwapOn: false

EOF
# kubelet.service配置文件
cat <<EOF >/usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet
  • node执行脚本kubelet.sh
bash kubelet.sh node节点ip

bash kubelet.sh 192.168.48.130
  • 查看配置
[root@k8s-node01 ~]# cat /opt/kubernetes/cfg/kubelet

KUBELET_OPTS="--logtostderr=false \# 指定日志目录
--log-dir=/opt/kubernetes/logs \
--v=4 \
--address=192.168.48.130 \
--hostname-override=192.168.48.130 \# 当前主机名
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \# kubernetes自动生成
--experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \#bootstrap
--config=/opt/kubernetes/cfg/kubelet.config \# 配置信息
--cert-dir=/opt/kubernetes/ssl \# 证书
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"# 创建pod第一个容器引入镜像地址
  • 启动异常,可以查看系统日志
less /opt/kubernetes/logs/kubelet.INFO
less /var/log/messages -f
  • 或是kubelet日志
journalctl -u kubelet
  • 可能出现报错
failed to run Kubelet: cannot create certificate signing request: certificatesigningrequests.certificates.k8s.io is forbidden: User "kubelet-bootstrap" cannot create resource "certificatesigningrequests" in API group "certificates.k8s.io" at the cluster scope

创建用户绑定到系统集群角色是否正确???
	删除角色名字: kubectl delete clusterrolebinding kubelet-bootstrap  
	重新创建:kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
	# 之前把node-bootstrapper 写成 nodebootstrapper
  • 查看启动状态
systemctl restart kubelet
  • 启动成功后会向Master发送请求证书。在Master中执行如下命令查看请求签名
kubectl get csr
NAME                                                   AGE     REQUESTOR           CONDITION
node-csr-Ddql46qTy-HKhQ5ejzeGKpbbugXDII22zTLgRg4hFt0   4m29s   kubelet-bootstrap   Pending
  • Master颁发证书
kubectl certificate approve [NAME]
kubectl certificate approve node-csr-Ddql46qTy-HKhQ5ejzeGKpbbugXDII22zTLgRg4hFt0
  • 查看节点:
kubectl get node

proxy.sh

  • 编写proxy.sh脚本
#!/bin/bash

NODE_ADDRESS=$1

cat <<EOF >/opt/kubernetes/cfg/kube-proxy

KUBE_PROXY_OPTS="--logtostderr=true \\
--v=4 \\
--hostname-override=${NODE_ADDRESS} \\# 节点名字
--cluster-cidr=10.0.0.0/24 \\# 集群网段
--proxy-mode=ipvs \\# ipvs模式
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"

EOF

cat <<EOF >/usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy
  • 执行脚本
bash proxy.sh 192.168.48.130
  • 查看启动状态
ps -ef | grep proxy

node的扩容

  • 从已部署的node拷贝到其他node
scp -r /opt/kubernetes/ root@192.168.48.131:/opt/
scp /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.48.131:/usr/lib/systemd/system/
  • 在opt/kubernetes/cfg/目录下修改新node的ip
vi kubelet
	--address,--hostname-override 改成本机IP
vi kubelet.config 
	address 改成本机IP
vi vi kube-proxy
	--hostname-override 改成本机IP
  • 删除拷贝过来办法的证书
cd /opt/kubernetes/ssl/
rm -f *
  • 启动:
systemctl start kubelet
systemctl start kube-proxy
  • Master颁发证书
kubectl certificate approve node-csr-gz_UlTpuBdk04IlNgwyC2MfVIhgRDso_xdS3ypGcxzs
  • 查看节点
kubectl get node

13测试一下

# 创建一个nginx
kubectl create deployment nginx --image=nginx
# 暴漏应用 暴漏80端口
kubectl expose deployment nginx --port=80 --type=NodePort
[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP        15h
nginx        NodePort    10.0.0.40    <none>        80:40009/TCP   21m


  • 此时访问子节点 http://192.168.48.131:40009/http://192.168.48.130:40009/就有nginx了

  • 副本扩容

    kubectl scale deployment nignx --replicas=3
    
  • 此时查看kubectl get pods 就会有三个nginx

14.dashboard可视化部署

  • 先在node的节点上拉取镜像:

    # node 节点拉取镜像
    docker pull lizhenliang/kubernetes-dashboard-amd64:v1.10.1
    
  • 拉取kubernetes-dashboard.yaml

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
  • 修改kubernetes-dashboard.yaml
vi kubernetes-dashboard.yaml
# 修改镜像地址
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 改为 image: lizhenliang/kubernetes-dashboard-amd64:v1.10.1

# 在Dashboard Service下spec新增type: NodePor 将其暴漏出来
# 并在ports新增一个端口  nodePort: 3000

# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001
  selector:


  • 将修改的kubernetes-dashboard.yaml 应用
kubectl apply -f kubernetes-dashboard.yaml 
  • 查看运行
kubectl get pods -n kube-system
  • 访问页面,因是https请求,它的证书不可信,所以直接跳过:
https://192.168.48.130:30001/
  • 跳过后出现如下页面

  • 创建一个serviceaccount账号

    kubectl create serviceaccount dashboard-admin -n kube-system
    # 名字叫dashboard-admin
    
  • 将创建账号进行权限绑定

    kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
    # dashboard-admin 具有超级管理员的权限
    
  • 这里使用token认证,我们执行命令拿去token

    kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
    
  • 展示ui

  • 转载
    转载自:李振良博客

posted @ 2021-03-14 17:46  是阿凯啊  阅读(182)  评论(0编辑  收藏  举报