云原生技术的发展趋势正在朝着利用 Kubernetes 作为公共抽象层来实现高度一致的、跨云、跨环境的的应用交付而不断迈进。然而,尽管 Kubernetes 在屏蔽底层基础架构细节方面表现出色,它并没有在混合与分布式的部署环境之上引入上层抽象来为软件交付进行建模。我们已经看到,这种缺乏统一上层抽象的软件交付过程,不仅给降低了生产力、影响了用户体验,甚至还会导致生产中出现错误和故障。
今天,越来越多的应用研发团队期盼着这样一个平台:它既能够简化面向混合环境(多集群/多云/混合云/分布式云)的应用交付过程;同时又足够灵活可以随时满足业务不断高速变化所带来的迭代压力。然而,尽管平台团队很希望能帮上忙,但构建这样一个面向混合交付环境同时又高可扩展的应用交付系统,着实是一项令人生畏的任务。
KubeVela 通过以下设计,使得面向混合/多云环境的应用交付变得非常简单高效:
完全以应用为中心 - KubeVela 创新性的提出了开放应用模型(OAM)来作为应用交付的顶层抽象,并通过声明式的交付工作流来捕获面向混合环境的微服务应用交付的整个过程,甚至连多集群分发策略、流量调配和滚动更新等运维特征,也都声明在应用级别。用户无需关心任何基础设施细节,只需要专注于定义和部署应用即可。 可编程式交付工作流 - KubeVela 的交付模型是利用 CUE 来实现的。CUE 是一种诞生自 Google Borg 系统的数据配置语言,它可以将应用交付的所有步骤、所需资源、关联的运维动作以可编程的方式粘合成一个 DAG(有向无环图)来作为最终的声明式交付计划。相比于其他系统的复杂性和不可扩展性,KubeVela 基于 CUE 的实现不仅使用简单、扩展性极强,也更符合现代 GitOps 应用交付的趋势与要求。 基础设施无关 - KubeVela 是一个完全与运行时基础设施无关的应用交付与管理控制平面。所以它可以按照你定义的工作流与策略,面向任何环境交付和管理任何应用组件,比如:容器、云函数、数据库,甚至 网络和虚拟机实例等等。
CoreDNS是一款新型的dns权威服务器
| 软件名 | 定位 | 优点 | 缺点 |
|---|---|---|---|
| bind/powerdns | 权威dns, 包括NS,A,CNAME,PTR,TXT | 可靠稳定,功能强大 | 代码古老,配置繁琐,性能不高 |
| dnsmasq | 缓存dns, 包括A,CNAME,TXT | 配置简单,可靠稳定 | 不能rewrite,性能不高 |
| unbound | 缓存dns, 包括A | 配置简单,性能高,支持tcp查询 | 可靠稳定(没测试),不能CNAME |
| coredns | 权威dns, 包括NS,A,CNAME,PTR,TXT | 配置超简单,可靠稳定, 性能高,无依赖(go) 支持插件体系, 支持etcd作为数据库条目 | 暂无 |
.:253 { errors log stdout health localhost:8080 cache { success 30000 300 denial 1024 5 prefetch 1 1m } loadbalance round_robin #新增以下一行Template插件,将AAAA记录类型拦截,返回空(NODATA) template IN AAAA . rewrite continue { ttl regex (.*) 180 } rewrite stop name regex ^robin.x.upyun.com gw1.service.upyun answer name gw1.service.upyun robin.x.upyun.com rewrite stop { name regex ^(kuzan|vivi|slardar|rds).upyun.local {1}.service.upyun answer name ^(kuzan|vivi|slardar|rds).service.upyun {1}.upyun.local } file /opt/coredns/upyun.local.zone upyun.local proxy cdnlog-cn-hangzhou.aliyuncs.com 211.140.13.188 211.140.188.188 proxy service.upyun 192.168.13.250:8600 192.168.13.230:8600 { policy sequential fail_timeout 1s max_fails 3 spray protocol dns } forward . 119.29.29.29 180.76.76.76 114.114.114.114 { policy round_robin health_check 5s retry_failed 3 except upyun.local service.upyun } }
$TTL 10 @ IN SOA ns1.upyun.local. root.upyun.local. ( 2 ;serial 300 ; refresh 1800 ; retry 10 ; expire 300 ; minimum ) ; used by haiyang.shao for apisix updc6 IN CNAME api ; used by shaohy for apisix gw1 api 10 IN A 192.168.5.91 api 10 IN A 192.168.5.92 api 10 IN A 192.168.5.93 api 10 IN A 192.168.5.94
upstream dns_load { server 192.168.13.229:253 weight=10 max_fails=5 fail_timeout=1s; server 192.168.13.230:253 weight=10 max_fails=5 fail_timeout=1s; server 192.168.13.231:253 weight=10 max_fails=5 fail_timeout=1s; server 192.168.144.1:253 weight=10 max_fails=5 fail_timeout=1s backup; server 192.168.144.2:253 weight=10 max_fails=5 fail_timeout=1s backup; server 192.168.144.3:253 weight=10 max_fails=5 fail_timeout=1s backup; } server { listen 192.168.21.20:53 udp; proxy_pass dns_load; proxy_timeout 30s; proxy_connect_timeout 30s; access_log logs/dns_access.log main; }
net.ipv4.tcpfintimeout=5
net.netfilter.nfconntrackmax=3000000
upstream ntpd_load { server ntp.aliyun.com:123 weight=5 max_fails=2 fail_timeout=5s; server ntp.ntsc.ac.cn:123 weight=5 max_fails=2 fail_timeout=5s; server asia.pool.ntp.org:123 weight=5 max_fails=2 fail_timeout=5s; server ntp1.aliyun.com:123 weight=5 max_fails=2 fail_timeout=5s backup; } server { listen 192.168.21.20:123 udp; proxy_pass ntpd_load; proxy_timeout 30s; proxy_connect_timeout 30s; }
sudo yum install -y https://repos.apiseven.com/packages/centos/apache-apisix-repo-1.0-1.noarch.rpm yum install -y apisix apisix-dashboard apisix init_etcd apisix init systemctl start apisix systemctl enable apisix systemctl start apisix-dashboard systemctl enable apisix-dashboard
apisix: enable_admin: true stream_proxy: # TCP/UDP proxy udp: # UDP proxy address list - 192.168.12.19:53 - 192.168.12.19:123 - 192.168.12.19:8600 discovery: consul: servers: - "http://192.168.13.229:8500" - "http://192.168.13.230:8500" - "http://192.168.13.231:8500" deployment: role: traditional role_traditional: config_provider: etcd etcd: use_grpc: true timeout: 3600 host: - "http://127.0.0.1:2379" prefix: "/apisix"
curl http://127.0.0.1:9180/apisix/admin/stream_routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "server_addr": "192.168.12.19", "server_port": 123, "upstream": { "nodes": { "ntp.aliyun.com:123": 1, "ntp.ntsc.ac.cn:123": 1, "asia.pool.ntp.org:123": 1 }, "type": "roundrobin" } }' curl http://127.0.0.1:9180/apisix/admin/stream_routes/3 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "server_addr": "192.168.12.19", "server_port": 8600, "upstream": { "nodes": { "192.168.13.229:8600": 1, "192.168.13.230:8600": 1, "192.168.13.231:8600": 1, "192.168.13.232:8600": 1, }, "type": "roundrobin" } }'
#hash: v0.1.1-30b3ffd kernel.core_uses_pid=1 kernel.pid_max=4194303 kernel.ctrl-alt-del=1 kernel.msgmnb=65536 kernel.msgmax=65536 kernel.shmmni=4096 kernel.shmmax=8589934592 kernel.shmall=8589934592 kernel.sem=250 32000 100 128 # Increase number of incoming connections.max=65535 net.core.somaxconn=8192 net.core.rmem_default=131072 net.core.wmem_default=131072 net.core.rmem_max=33554432 net.core.wmem_max=33554432 net.core.dev_weight=512 net.core.optmem_max=262144 net.core.netdev_budget=1024 net.core.netdev_max_backlog=262144 net.ipv4.neigh.default.gc_thresh1=10240 net.ipv4.neigh.default.gc_thresh2=40960 net.ipv4.neigh.default.gc_thresh3=81920 # for lvs tunnel mode net.ipv4.conf.all.proxy_arp=0 # http://blog.clanzx.net/2013/10/30/arp-filter.html net.ipv4.conf.all.arp_announce=2 net.ipv4.conf.default.arp_announce=2 net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.default.arp_ignore=1 net.ipv4.conf.all.arp_filter=1 net.ipv4.conf.default.arp_filter=1 net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.all.rp_filter=0 # https://mellowd.co.uk/ccie/?tag=pmtud # Warning,if MTU=9000 set 1, else 0 is good net.ipv4.tcp_mtu_probing=0 net.ipv4.ip_no_pmtu_disc=0 net.ipv4.tcp_slow_start_after_idle=0 # Do not cache metrics on closing connections net.ipv4.tcp_no_metrics_save=1 # Protect Against TCP Time-Wait net.ipv4.tcp_rfc1337=1 net.ipv4.conf.default.accept_source_route=0 net.ipv4.conf.default.accept_redirects=0 net.ipv4.conf.default.secure_redirects=0 net.ipv4.conf.all.accept_source_route=0 net.ipv4.conf.all.accept_redirects=0 net.ipv4.conf.all.secure_redirects=0 net.ipv4.ip_forward=1 net.ipv4.ip_local_port_range=9000 65535 net.ipv4.icmp_echo_ignore_broadcasts=1 net.ipv4.icmp_ignore_bogus_error_responses=1 net.ipv4.tcp_timestamps=1 net.ipv4.tcp_sack=1 net.ipv4.tcp_dsack=1 net.ipv4.tcp_window_scaling=1 net.ipv4.tcp_rmem=4096 102400 16777216 net.ipv4.tcp_wmem=4096 102400 16777216 #net.ipv4.tcp_mem=3145728 4194304 6291456 net.ipv4.tcp_mem=786432 1048576 1572864 net.ipv4.tcp_syncookies=1 net.ipv4.tcp_syn_retries=3 net.ipv4.tcp_synack_retries=5 net.ipv4.tcp_retries1=3 net.ipv4.tcp_retries2=15 net.ipv4.tcp_fin_timeout=30 net.ipv4.tcp_max_syn_backlog=262144 net.ipv4.tcp_max_orphans=262144 net.ipv4.tcp_frto=2 net.ipv4.tcp_thin_dupack=0 net.ipv4.tcp_reordering=3 net.ipv4.tcp_early_retrans=3 net.ipv4.tcp_tw_recycle=0 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_keepalive_time=30 net.ipv4.tcp_keepalive_intvl=10 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_max_tw_buckets=600000 net.ipv4.tcp_congestion_control=bbr net.ipv4.netfilter.ip_conntrack_max=600000 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=1 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait=1 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=1 net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=15 net.netfilter.nf_conntrack_max=600000 net.netfilter.nf_conntrack_tcp_timeout_close_wait=1 net.netfilter.nf_conntrack_tcp_timeout_fin_wait=1 net.netfilter.nf_conntrack_tcp_timeout_time_wait=1 net.netfilter.nf_conntrack_tcp_timeout_established=15 vm.swappiness=0 vm.dirty_writeback_centisecs=9000 vm.dirty_expire_centisecs=18000 vm.dirty_background_ratio=5 vm.dirty_ratio=10 vm.overcommit_memory=1 vm.overcommit_ratio=50 vm.max_map_count=200000 fs.file-max=524288 fs.aio-max-nr=1048576
禁用conntrack跟踪模块
blacklist iptable_nat blacklist nf_nat blacklist nf_conntrack blacklist nf_conntrack_ipv4 blacklist nf_defrag_ipv4
用iptables禁用跟踪
iptables -t raw -A PREROUTING -p ALL -j NOTRACK iptables -t raw -A OUTPUT -p ALL -j NOTRACK
systemctl stop firewalld systemctl disable firewalld systemctl start iptables systemctl enable iptables iptables -F service iptables save [root@k8s-master ~]# firewall-cmd --permanent --add-port=6443/tcp [root@k8s-master ~]# firewall-cmd --permanent --add-port=2379-2380/tcp [root@k8s-master ~]# firewall-cmd --permanent --add-port=10250/tcp [root@k8s-master ~]# firewall-cmd --permanent --add-port=10251/tcp [root@k8s-master ~]# firewall-cmd --permanent --add-port=10252/tcp [root@k8s-master ~]# firewall-cmd --permanent --add-port=10255/tcp [root@k8s-master ~]# firewall-cmd --reload [root@k8s-master ~]# modprobe br_netfilter [root@k8s-master ~]# echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
修改Docker配置文件/etc/default/docker如下:
DOCKER_OPTS="--registry-mirror=http://aad0405c.m.daocloud.io"
修改Docker.service允许FORWARD为ACCEPT
ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -j ACCEPT
# 编辑配置文件 vim /etc/etcd/etcd.conf # 样例配置如下 # 节点名称 ETCD_NAME=etcd0 # 数据存放位置 ETCD_DATA_DIR="/var/lib/etcd/etcd0" # 监听其他 Etcd 实例的地址 ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" # 监听客户端地址 ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001" # 通知其他 Etcd 实例地址 ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.154:2380" # 初始化集群内节点地址 ETCD_INITIAL_CLUSTER="etcd0=http://192.168.1.154:2380,etcd1=http://192.168.1.156:2380,etcd2=http://192.168.1.249:2380" # 初始化集群状态,new 表示新建 ETCD_INITIAL_CLUSTER_STATE="new" # 初始化集群 token ETCD_INITIAL_CLUSTER_TOKEN="mritd-etcd-cluster" # 通知 客户端地址 ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.154:2379,http://192.168.1.154:4001"
集群搭建好后,在任意节点执行
etcdctl member list 可列所有集群节点信息 etcdctl cluster-health 检查集群健康状态
很有可能是查询的时候需要指定证书
etcdctl --ca-file /etc/kubernetes/ssl/ca.pem --endpoints "https://127.0.0.1:2379" cluster-health
原因是:ETCDCLUSTERNODE_LIST中的ip必须在生成etcd TLS证书时在etcd-csr.json中的hosts字段中指定(Subject Alternative Name(SAN)),否则可能会得到这样的错误。
No help topic for 'snapshot'
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.13.137:2379 snapshot save etcd_2022_11_18_10.db
Error: context deadline exceeded
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.13.137:2379 snapshot save etcd_2022_11_18_10.db \ --cacert /etc/kubernetes/ssl/ca.pem \ --cert /etc/kubernetes/ssl/etcd.pem \ --key /etc/kubernetes/ssl/etcd-key.pem
恢复操作
ETCDCTL_API=3 etcdctl snapshot restore snapshot.db --name m3 --data-dir=/home/etcd_data
这两个一般用在应用yaml描述文件中,起到的作用类似于docker -p选项
这两个一般用在service中,service 的类型为cluster ip时候:
这一个一般用在service中,service的类型为nodeport:
targetPort在pod上、负责与kube-proxy代理的port和Nodeport数据进行通信
[K8S] k8s-m1 ansible_ssh_port=65422 ansible_ssh_host=192.168.13.134 ETCD="yes" K8S="both" k8s-n2 ansible_ssh_port=65422 ansible_ssh_host=192.168.13.137 ETCD="yes" K8S="slave" k8s-n3 ansible_ssh_port=65422 ansible_ssh_host=192.168.13.140 ETCD="yes" K8S="slave"
打包并解压
K8S_SSL_Repo="http://devops.upyun.com/upyun.k8s.pem.tgz" tar zcvf upyun.k8s.pem.tgz etc/* ; tar zxvf upyun.k8s.pem.tgz -C /
下载回来的二进制放在upyun.k8s.bin.tgz下重新打包
K8S_BIN_Repo="http://devops.upyun.com/upyun.k8s.bin.1.23.tgz"
ansible-playbook -i lists_k8s main.yml -e "host=all" -t init
ansible-playbook -i lists_k8s main.yml -e "host=all" -t etcd
ansible-playbook -i lists_k8s main.yml -e "host=all" -t k8s-bin,kube-router
systemctl status kube-apiserver -l journalctl -xeu kube-apiserver grep "kube-apiserver: E" /var/log/messages
yum install -y bash-completion kubectl completion bash > ~/.kube/completion.bash.inc source ~/.kube/completion.bash.inc source ~/.bash_profile
kubectl get componentstatuses kubectl describe nodes k8s-m1
kubectl get csr kubectl certificate approve node-csr-xxxx
kubectl apply -f generic-kuberouter-all-features.yaml kubectl get nodes -o wide --all-namespaces
kubectl apply -f coredns.yaml
利用 Net Namespace 可以为 Docker 容器创建隔离的网络环境,容器具有完全独立的网络栈,与宿主机隔离。
我们在使用docker run创建 Docker 容器时,可以使用–network=选项指定容器的网络模式,Docker 有以下 4 种网络模式:
host 模式,使用–network=host指定,不支持多主机; bridge 模式,使用–network=bridge指定,默认设置,不支持多主机; container 模式,使用–network=container:NAMEorID指定,即joiner 容器,不支持多主机; none 模式,使用–network=none指定,不支持多主机。
kubectl create clusterrolebinding kubelet-bootstrap \ --clusterrole=system:node-bootstrapper \ --user=kubelet-bootstrap kubectl create clusterrolebinding kubelet-bootstrap \ --clusterrole=system:node-bootstrapper \ --group=system:bootstrappers kubectl create clusterrolebinding kubelet-nodes \ --clusterrole=system:node \ --group=system:nodes
kubectl describe clusterrole system:kube-controller-manager kubectl delete clusterrole system:kube-controller-manager
mkcontroller(){ cat > kube-controller-csr.json <<EOF { "CN": "kubernetes", "hosts": [ EOF echo -en $HOST >> kube-controller-csr.json cat >> kube-controller-csr.json <<EOF "192.168.0.0/16", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "ZJ", "L": "HZ", "O": "system:kube-controller-manager", "OU": "$OU" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-csr.json | cfssljson -bare kube-controller }
# kube-controller-manager kubeconfig # 设置集群参数 kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=controller-manager.kubeconfig.${node_name} # 设置客户端认证参数 kubectl config set-credentials system:kube-controller-manager \ --client-certificate=/etc/kubernetes/ssl/kube-controller.pem \ --client-key=/etc/kubernetes/ssl/kube-controller-key.pem \ --embed-certs=true \ --kubeconfig=controller-manager.kubeconfig.${node_name} # 设置上下文参数 kubectl config set-context system:kube-controller-manager \ --cluster=kubernetes \ --user=system:kube-controller-manager \ --kubeconfig=controller-manager.kubeconfig.${node_name} # 设置默认上下文 kubectl config use-context system:kube-controller-manager --kubeconfig=controller-manager.kubeconfig.${node_name}
Kubernetes 集群的监控方案目前主要有以下几种方案:
监控对象包括:
比较合适的架构:
#kubelet cAdvisor 默认在所有接口监听 4194 端口的请求, 以下iptables限制内网访问 ExecStartPost=/sbin/iptables -A INPUT -s 172.30.0.0/16 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/16 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP
和其他监控系统相比,Prometheus的特点包括:
Prometheus生态系统由多个组件组成,其中许多是可选的:
wget https://github.com/prometheus/prometheus/releases/download/v2.9.2/prometheus-2.9.2.linux-amd64.tar.gz tar zxvf prometheus-2.9.2.linux-amd64.tar.gz mv prometheus-2.9.2.linux-amd64 /opt/prometheus useradd -m -d /var/lib/prometheus -s /sbin/nologin prometheus chown -R prometheus:prometheus /opt/prometheus
vi /etc/profile.d/prometheus.sh
export PATH=$PATH:/opt/prometheus
vi /etc/systemd/system/prometheus.service
[Unit] Description=Prometheus Server Documentation=https://prometheus.io/docs/introduction/overview/ After=network-online.target [Service] User=prometheus Group=prometheus Restart=on-failure ExecStart=/opt/prometheus/prometheus \ --config.file=/opt/prometheus/prometheus.yml \ --storage.tsdb.path=/opt/prometheus/data \ --storage.tsdb.retention.time=30d \ --enable-feature=remote-write-receiver [Install] WantedBy=multi-user.target
机器安装:各种exporter,也可以自定义监控指标key
1. kill -HUP pid 2. curl -X POST http://localhost:9090/-/reload
prometheus官方提供了一个非常贴心的工具,prometool 可以检查配置文件是否正确,用法:(其他用法自行开发)
./promtool check config prometheus.yml
docker run -tid --restart=always --name=node_exporter \ --net="host" \ --pid="host" \ -v "/:/host:ro,rslave" \ quay.io/prometheus/node-exporter \ --path.rootfs /host
[Unit] Description=Node_exporter DefaultDependencies=no [Service] Type=simple User=node_exporter RemainAfterExit=yes ExecStart=/opt/node_exporter/node_exporter --collector.textfile.directory=/data/node_exporter/ --web.listen-address=:9100 #根据实际路径修改 Restart=on-failure [Install] WantedBy=multi-user.target
[program:node_exporter] command = /opt/node_exporter/node_exporter autostart = true autorestart = true stdout_logfile = NONE stderr_logfile = NONE
- job_name: 'node-exporter' static_configs: - targets: ['192.168.21.20:9100'] labels: instance: vpn
docker run -tid --restart=always -v /etc/ceph:/etc/ceph -p=9128:9128 digitalocean/ceph_exporter
- job_name: 'ceph-exporter' static_configs: - targets: ['192.168.146.11:9128','192.168.146.12:9128','192.168.146.13:9128','192.168.146.14:9128'] labels: instance: ceph
snmp_exporter 默认的snmp版本为1,并且没有指定 Community。
yum install -y gcc gcc-g++ make yum install -y net-snmp net-snmp-utils net-snmp-libs net-snmp-devel go get github.com/prometheus/snmp_exporter/generator cd ${GOPATH-$HOME/go}/src/github.com/prometheus/snmp_exporter/generator go build make mibs
version: 2 # SNMP version to use. Defaults to 2. auth: # Community string is used with SNMP v1 and v2. Defaults to "public". community: public
export MIBDIRS=mibs ./generator generate
[Unit] Description=prometheus After=network.target [Service] Type=simple User=prometheus ExecStart=/opt/snmp_exporter/snmp_exporter --config.file=/opt/snmp_exporter/snmp.yml Restart=on-failure [Install] WantedBy=multi-user.target
curl 'http://安装snmp_exporter的机器的IP:9116/snmp?target=被监控交换机IP'
- job_name: 'snmp' scrape_interval: 120s scrape_timeout: 120s static_configs: - targets: - 172.16.1.5 # 添加需要被监控交换机的ip labels: instance: h3c location: SAD metrics_path: /snmp params: module: [if_mib] #指定使用snmp_exporter程序的 if_mib 模块 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.5.76:9116 #指定snmp_exporter监控节点的代理服务器ip
GRANT REPLICATION CLIENT, PROCESS ON *.* TO 'exporter'@'127.0.0.1' identified by 'upyun.com123'; GRANT SELECT ON performance_schema.* TO 'exporter'@'127.0.0.1';
docker pull prom/mysqld-exporter docker run -d \ --net="host" \ -e DATA_SOURCE_NAME="exporter:upyun.com123@(127.0.0.1:3306)/" \ prom/mysqld-exporter
- job_name: 'mysql-exporter' static_configs: - targets: ['192.168.144.109:9104'] labels: instance: mysql
curl http://192.168.144.109:9104/metrics
Grafana Dashboard 有着非常漂亮的图表和布局展示,功能齐全的度量仪表盘和图形编辑器,支持Graphite、zabbix、InfluxDB、Prometheus和OpenTSDB作为数据源。
Grafana主要特性:
wget https://dl.grafana.com/oss/release/grafana-6.1.6.linux-amd64.tar.gz tar zxvf grafana-6.1.6.linux-amd64.tar.gz mv grafana-6.1.6 /opt/grafana
groupadd grafana useradd -g grafana -m -d /var/lib/grafana -s /sbin/nologin grafana
GRAFANA_USER=grafana GRAFANA_GROUP=grafana GRAFANA_HOME=/opt/grafana LOG_DIR=/var/log DATA_DIR=/var/lib/grafana MAX_OPEN_FILES=10000 CONF_DIR=/opt/grafana CONF_FILE=/opt/grafana/conf/grafana.ini RESTART_ON_UPGRADE=true PLUGINS_DIR=/var/lib/grafana/plugins PROVISIONING_CFG_DIR=/opt/grafana/conf/provisioning # Only used on systemd systems PID_FILE_DIR=/var/lib/grafana
ExecStart=/opt/grafana/bin/grafana-server \ --homepath /opt/grafana \ --config=${CONF_FILE} \ --pidfile=${PID_FILE_DIR}/grafana-server.pid \ cfg:default.paths.logs=${LOG_DIR} \ cfg:default.paths.data=${DATA_DIR} \ cfg:default.paths.plugins=${PLUGINS_DIR} \ cfg:default.paths.provisioning=${PROVISIONING_CFG_DIR}
如缺少插件则安装 饼图面板插件
for i in grafana-piechart-panel snuids-trafficlights-panel;do grafana-cli plugins install $i done vi /opt/grafana/conf/grafana.ini ... plugins = /data/grafana/plugins systemctl restart grafana
Grafana从4.0开始新增预警功能,下面简单介绍一下。Grafana告警设置分为两部分:
Notification配置:
其实就是配置告警途径,Grafana支持多种方式的告警:Email、webhook等。由于webhook比较通用,我们重点说下如何配置webhook。
Alert配置:
alert config页面设置报警阈值,和报警条件等。
在某些情况下除了Alertmanager已经内置的集中告警通知方式以外,对于不同的用户和组织而言还需要一些自定义的告知方式支持。通过Alertmanager提供的webhook支持可以轻松实现这一类的扩展。除了用于支持额外的通知方式,webhook还可以与其他第三方系统集成实现运维自动化,或者弹性伸缩等。
wget https://github.com/prometheus/alertmanager/releases/download/v0.17.0/alertmanager-0.17.0.linux-amd64.tar.gz tar zxvf alertmanager-0.17.0.linux-amd64.tar.gz mv alertmanager-0.17.0.linux-amd64 /opt/alertmanager
vi alertmanager.yml
global: resolve_timeout: 5m route: receiver: webhook group_wait: 30s group_interval: 5m repeat_interval: 4h group_by: [alertname] routes: - receiver: webhook group_wait: 10s match: team: node receivers: - name: webhook webhook_configs: - url: http://localhost:8060/dingtalk/webhook1/send send_resolved: true
vi /etc/systemd/system/alertmanager.service
[Unit] Description=Alertmanager After=network.target [Service] Type=simple User=prometheus ExecStart=/opt/alertmanager/alertmanager --config.file=/opt/alertmanager/alertmanager.yml --storage.path=/data/alertmanager Restart=on-failure [Install] WantedBy=multi-user.target
Prometheus除了存储数据外,还提供了一种强大的功能表达式语言PromQL,允许用户实时选择和汇聚时间序列数据。
表达式的结果可以在浏览器中显示为图形,也可以显示为表格数据,或者由外部系统通过 HTTP API 调用。通过PromQL用户可以非常方便地查询监控数据,或者利用表达式进行告警配置
钉钉自定义“新内测报警”
13396815591/GeminisXXX https://oapi.dingtalk.com/robot/send?access_token=0f0b2e4b29ccedbfa6ef2b609dbbc1dbda3aa074c4f198337acad55119f3cba5
用docker方式安装prometheus-webhook-dingtal
docker pull timonwong/prometheus-webhook-dingtalk docker run -tid --restart=always --name dingtalk -p 8060:8060 timonwong/prometheus-webhook-dingtalk --ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token=token1"
ifconfig bond0 mtu 9000 up ip link set dev bond0 mtu 9000
注意: 网络参数MTU在容器云跨机房互通上要协商一致(/sys/class/net/ethX/mtu),如 9000就需要设备一致.
Kube-router使用LVS作为服务代理。 LVS支持丰富的调度算法。您可以为该服务添加注释以选择一个调度算法。
当一个服务没有注释时,默认情况下选择“轮询”调度策略
For least connection scheduling use: kubectl annotate service my-service "kube-router.io/service.scheduler=lc" For round-robin scheduling use: kubectl annotate service my-service "kube-router.io/service.scheduler=rr" For source hashing scheduling use: kubectl annotate service my-service "kube-router.io/service.scheduler=sh" For destination hashing scheduling use: kubectl annotate service my-service "kube-router.io/service.scheduler=dh"
redis-cli --cluster create --cluster-replicas 1 \ 10.109.218.140:6379 10.100.194.81:6379 \ 10.105.204.209:6379 10.97.40.13:6379 \ 10.108.48.154:6379 10.105.130.101:6379 \ 10.96.33.238:6379 10.97.154.41:6379 redis-cli -c -h 10.109.218.140 -p 6379 cluster info
Secret解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。
目前Secret的类型有3种:
#Opaque类型的数据是一个map类型,要求value是base64编码格式: ##创建admin账户 echo -n "admin" | base64 YWRtaW4= echo -n "1f2d1e2e67df" | base64 MWYyZDFlMmU2N2Rm
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ceph-web provisioner: kubernetes.io/rbd parameters: monitors: 192.168.146.11,192.168.146.12,192.168.146.13,192.168.146.14 adminId: admin adminSecretName: ceph-secret adminSecretNamespace: lnmp pool: rbd userId: admin userSecretName: ceph-secret fsType: xfs imageFormat: "1" imageFeatures: "layering" --- apiVersion: v1 kind: Secret metadata: name: ceph-secret namespace: lnmp type: "kubernetes.io/rbd" data: # 这个就是 ceph.client.admin.keyring中的key做 base64加密 key: QVFESUQzTmEyeFcrTnhBQXlPdlYxZ0NwWHFqR0tlR29wdDYxNkE9PQ==
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config-vol
namespace: lnmp
labels:
app: nginx
data:
default.conf: |
server {
listen 80;
server_name "";
root /usr/html;
index index.php index.html index.htm;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location ~.*.(js|css|html|png|jpg|gif|mp4|svg|apk|pbk)$ {
expires 7d;
}
location ~ \.php$ {
fastcgi_pass php-svc:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
apiVersion: apps/v1beta1 # for versions before 1.8.0 use apps/v1beta1 kind: Deployment metadata: name: nginx-deployment namespace: lnmp labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: docker.io/smebberson/alpine-nginx ports: - containerPort: 80 volumeMounts: - name: nfs-pv mountPath: /usr/html - name: config mountPath: /etc/nginx/conf.d volumes: # 宿主机上的目录 - name: nfs-pv nfs: path: /mnt/nfs server: 192.168.13.142 - name: config configMap: name: nginx-config-vol --- apiVersion: v1 kind: Service metadata: name: nginx-svc namespace: lnmp labels: app: nginx spec: type: NodePort selector: app: nginx ports: - port: 80 targetPort: 80 nodePort: 30080
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: mysql-secrets
namespace: lnmp
labels:
app: mysql
data:
#root
root-password: dXB5dW4xMjM=
#upyun123
root-user: cm9vdA==
apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: mysql namespace: lnmp spec: serviceName: mysql-svc replicas: 3 template: metadata: labels: app: mysql spec: initContainers: - name: copy-mariadb-config image: busybox command: ['sh', '-c', 'cp /configmap/* /etc/mysql/conf.d'] volumeMounts: - name: configmap mountPath: /configmap - name: config mountPath: /etc/mysql/conf.d containers: - name: mysql image: ausov/k8s-mariadb-cluster ports: - containerPort: 3306 name: mysql - containerPort: 4444 name: sst - containerPort: 4567 name: replication - containerPort: 4568 name: ist env: - name: GALERA_SERVICE value: "mysql-svc" - name: POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secrets key: root-password - name: MYSQL_ROOT_USER valueFrom: secretKeyRef: name: mysql-secrets key: root-user - name: MYSQL_INITDB_SKIP_TZINFO value: "yes" readinessProbe: exec: command: ["bash", "-c", "mysql -uroot -p\"${MYSQL_ROOT_PASSWORD}\" -e 'show databases;'"] initialDelaySeconds: 20 timeoutSeconds: 5 volumeMounts: - name: config mountPath: /etc/mysql/conf.d - name: datadir mountPath: /var/lib/mysql volumes: - name: config emptyDir: {} - name: configmap configMap: name: mysql-config-vol items: - path: "galera.cnf" key: galera.cnf - path: "mariadb.cnf" key: mariadb.cnf volumeClaimTemplates: - metadata: name: datadir annotations: volume.beta.kubernetes.io/storage-class: "ceph-web" spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi --- apiVersion: v1 kind: Service metadata: annotations: service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" name: mysql-svc namespace: lnmp labels: app: mysql tier: data spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 name: mysql clusterIP: None
# kube-apiserver : --authorization-mode=RBAC kubectl create clusterrolebinding kubelet-node-clusterbinding --clusterrole=system:node --user=system:node:k8s-m1 kubectl get clusterrolebindings -o wide --all-namespaces
分布式追踪系统发展很快,种类繁多,但核心步骤一般有三个:代码埋点,数据存储、查询展示。
yum install -y ceph-common # 每个节点都要安装
获取pvc信息
kubectl get pvc --all-namespaces |awk '/pvc-/{print $4}' > xx #!/bin/sh while read LINE;do echo $LINE rbd info kubernetes-dynamic-$LINE done < xx
For non-RBAC deployments, you'll need to edit the resulting yaml before applying it:
Remove the line serviceAccountName: coredns from the Deployment section. Remove the ServiceAccount, ClusterRole, and ClusterRoleBinding sections.
将 Nginx 或 HAProxy 部署到 Kubernetes 可将 Nginx 或 HAProxy 作为 ReplicaSet 或 DaemonSet(指定 Nginx 或 HAProxy 容器映像)部署到 Kubernetes。 使用 ConfigMap 存储代理的配置文件,然后将 ConfigMap 装载为卷。 创建 LoadBalancer 类型的服务,以通过 Azure 负载均衡器公开网关。
另外,请考虑在群集中的一组专用节点上运行网关。 这种做法的好处包括:
隔离。 所有入站流量将转到可与后端服务相隔离的固定一组节点。 稳定的配置。 如果网关配置不当,则整个应用程序可能不可用。 性能。 出于性能原因,可能需要对网关使用特定的 VM 配置。Traefik V2.1是一款比Nginx更方便的开源反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。目前支持Docker、Swarm、Mesos/Marathon、 Mesos、Kubernetes、Consul、Etcd、Zookeeper、BoltDB、Rest API等等后端模型。
KubeVela 围绕着云原生应用交付和管理场景展开,背后的应用交付模型是 Open Application Model,简称 OAM 。
每一个应用部署计划都由四个部分组成,分别是组件制品、运维能力、部署策略和工作流。其格式如下:
组件制品(Component): 组件定义一个应用包含的待交付制品(二进制、Docker 镜像、Helm Chart…)或云服务。我们认为一个应用部署计划部署的是一个微服务单元,里面主要包含一个核心的用于频繁迭代的服务,以及一组服务所依赖的中间件集合(包含数据库、缓存、云服务等),一个应用中包含的组件数量应该控制在约 15 个以内。 运维特征(Trait): 运维特征是可以随时绑定给待部署组件的、模块化、可拔插的运维能力,比如:副本数调整(手动、自动)、数据持久化、 设置网关策略、自动设置 DNS 解析等。 应用策略(Policy): 应用策略负责定义指定应用交付过程中的策略,比如多集群部署的差异化配置、资源放置策略、安全组策略、防火墙规则、SLO 目标等。 工作流步骤(Workflow Step): 工作流由多个步骤组成,允许用户自定义应用在某个环境的交付过程。典型的工作流步骤包括人工审核、数据传递、多集群发布、通知等。
helm repo add kubevela https://charts.kubevela.net/core helm repo update helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wait --set multicluster.enabled=false # vela addon disable velaux # vela uninstall # helm uninstall -n vela-system kubevela # kubectl get crd |grep oam | awk '{print $1}' | xargs kubectl delete crd # rm -rf ~/.vela
# 此命令用于在管控集群创建命名空间 vela env init prod --namespace prod vela up -f https://kubevela.net/example/applications/first-app.yaml vela delete first-vela-app #正常情况下应用完成第一个目标部署后进入暂停状态(workflowSuspending)。 vela status first-vela-app #人工审核,批准应用进入第二个目标部署 vela workflow resume first-vela-app #通过下述方式来访问该应用 vela port-forward first-vela-app 8000:8000 curl http://127.0.0.1:8000 <pre> Hello KubeVela! Make shipping applications more enjoyable. , //, //// ./ /////* ,/// /////// .///// //////// /////// ///////// //////// ////////// ,///////// /////////// ,////////// ///////////. ./////////// //////////// //////////// ////////////. *//////////// ////////////* #@@@@@@@@@@@* ..,,***/ ///////////// /@@@@@@@@@@@# *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@& .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .&@@@* *@@@& ,@@@&. _ __ _ __ __ _ | |/ /_ _ | |__ ___\ \ / /___ | | __ _ | ' /| | | || '_ \ / _ \\ \ / // _ \| | / _` | | . \| |_| || |_) || __/ \ V /| __/| || (_| | |_|\_\\__,_||_.__/ \___| \_/ \___||_| \__,_|
first-app.yaml
apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: first-vela-app spec: components: - name: express-server type: webservice properties: image: oamdev/hello-world ports: - port: 8000 expose: true traits: - type: scaler properties: replicas: 1 policies: - name: target-default type: topology properties: # local 集群即 Kubevela 所在的集群 clusters: ["local"] namespace: "default" - name: target-prod type: topology properties: clusters: ["local"] # 此命名空间需要在应用部署前完成创建 namespace: "prod" - name: deploy-ha type: override properties: components: - type: webservice traits: - type: scaler properties: replicas: 2 workflow: steps: - name: deploy2default type: deploy properties: policies: ["target-default"] - name: manual-approval type: suspend - name: deploy2prod type: deploy properties: policies: ["target-prod", "deploy-ha"]
Maesh与Kubernetes本机集成,可以使用Helm安装。Maesh需要Kubernetes 1.11或更高版本,因为它利用CoreDNS来运行Maesh端点,而不是标准Kubernetes服务端点。Maesh端点与服务并排运行,并且默认情况下是选择加入的。在将现有服务添加到网格之前,它们不会受到影响,从而可以将Maesh逐步集成到应用程序中。
Maesh功能集建立在Golang开源反向代理和负载均衡器Traefik之上,包括Traefik的核心组件。网络可观察性通过OpenTracing实现,OpenTracing是供应商中立的API规范和用于分布式跟踪的工具框架。诸如负载平衡,重试,断路器和速率限制之类的流量管理控件可以定义为Kubernetes服务上的注释。
Maesh还支持使用SMI(服务网格技术的标准接口)进行配置。当在SMI模式下配置Maesh时,将明确启用访问和路由。默认情况下,所有路由和访问都被拒绝。启用SMI 是安装服务网格时定义的Maesh 静态配置的一部分。
Maesh同时支持TCP和HTTP。在HTTP模式下,Maesh依靠Traefik在虚拟主机,路径,标头,cookie上启用路由。使用TCP模式可以与SNI路由支持集成。在单个群集中可以同时使用两种模式。
若要使用Maesh,请不要将服务引用为<servicename>.<namespace>,而是将服务引用为<servicename>.<namespace> .maesh。 这些引用将通过Maesh服务网格访问和路由请求。通过这种方法,一些服务可以通过服务网格运行,而其他服务则不需要。
apiVersion: v1 kind: ServiceAccount metadata: name: tiller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: tiller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller namespace: kube-system
--- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-path provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer --- apiVersion: v1 kind: PersistentVolume metadata: name: local-storage spec: capacity: storage: 1Gi # volumeMode field requires BlockVolume Alpha feature gate to be enabled. volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-m1 - k8s-n2 - k8s-n3
helm repo add maesh https://containous.github.io/maesh/charts helm repo update helm init --service-account tiller helm list helm del --purge maesh helm install --name=maesh --namespace=maesh maesh/maesh kubectl -n kube-system get pods,deployment,svc kubectl get all -n maesh kubectl delete deployment tiller-deploy --namespace=kube-system kubectl delete svc tiller-deploy --namespace=kube-system
服务网格是一个专门的基础设施层,用来处理服务到服务之间的通信。服务网格用来解决微服务运维方面的一些复杂性,它围绕可观测性、重试/超时、服务发现以及动态代理等方面的最佳实践进行了封装,上述所提及的这些关注点通常会妨碍微服务的部署。
服务网格领域的几个流行工具包括:Istio、 Linkerd2、Cilium、Consul Connect
♥ 通过Service Mesh的控制平面,控制范围从微服务体系扩展到了API Gateway体系。
将API Gateway纳入Service Mesh体系
kubectl apply -f install/kubernetes/istio-demo.yaml
早期的做法
cd istio-0.7 kubectl create -f istio-sidecar-injector-configmap-release.yaml --dry-run -o=jsonpath='{.data.config}' > inject-config.yaml kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml istioctl kube-inject \ --injectConfigFile inject-config.yaml \ --meshConfigFile mesh-config.yaml \ --filename path/to/original/deployment.yaml \ --output deployment-injected.yaml kubectl apply -f deployment-injected.yaml
kubectl -n istio-system exec -ti prometheus -- nslookup istio-statsd-prom-bridge
kubectl -n istio-system port-forward \ $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') \ 3000:3000 & iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 3000 -j DNAT --to-destination 127.0.0.1:3000
kubectl -n istio-system port-forward \ $(kubectl -n istio-system get pod -l app=servicegraph -o jsonpath='{.items[0].metadata.name}') \ 8088:8088 & iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8088 -j DNAT --to-destination 127.0.0.1:8088 http://192.168.13.142:8088/dotviz
INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT src=`ip -4 route get 1.1.1.1|awk '/src/{print $NF}'` kubectl get svc -n istio-system | awk '{ \ if($1 ~ /grafana/ || $1 ~ /servicegraph/ || $1 ~ /jaeger-query/) { \ gsub("/TCP","",$5);print "iptables -t nat -A PREROUTING -p tcp -d","'$src'","--dport",$5,"-j DNAT --to-destination",$3":"$5 \ } \ }'
kubectl apply -f istio-demo.yaml kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products route: - destination: host: productpage port: number: 9080
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 weight: 50 - destination: host: reviews subset: v3 weight: 50
ansible-playbook -i lists_k8s main.yml -e "host=all" -t init # 初始化跟自动化脚本安装k8s的步骤一致
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF
yum makecache fast yum install -y kubelet kubeadm kubectl systemctl enable kubelet ln -s /usr/libexec/docker/docker-runc-current /usr/local/bin/docker-runc # 如果docker version <= 1.13
kubeadm reset # 先清理环境 kubeadm init \ --kubernetes-version=v1.10.3 \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=0.0.0.0
kubectl get cs kubectl get csr NAME AGE REQUESTOR CONDITION node-csr-9mU9zhj0Q_OA3DyPeupKZrirTsOMLM0Ahl2Mjit6bEI 18m kubelet-bootstrap Approved,Issued node-csr-HrGdN7amR0Vp1zSfvPFZMbD89U3R9nkHnVViCm-d_O8 18m kubelet-bootstrap Approved,Issued node-csr-RPntnuINm2iVEYUKGSDLJHkyta9yq75mTZnFa_g9OaE 18m kubelet-bootstrap Approved,Issued Approved = controller-manager没有配置好,检查是否加上了ssl授权 Approved,Issued = 确认授权 OK
kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION k8s-m1 NotReady <none> 1m v1.11.0 k8s-n1 NotReady <none> 1m v1.11.0 k8s-n2 NotReady <none> 1m v1.11.0 NotReady = nodes间的网络有问题
kubectl get pods -o wide --all-namespaces
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl apply -f kube-flannel.yml #kubectl apply -f http://mirror.faasx.com/kubernetes/installation/hosted/kubeadm/1.7/calico.yaml
kubectl taint nodes k8s-m1 node-role.kubernetes.io/master-
kubectl logs kubectl get events kubectl describe pod
当Docker 运行在overlay2存储驱动上时,需要d_type特性的支持才能正常工作,Docker1.13以后加入了对此的检查,可以运行docker info命令来查看文件系统是否支持d_type这个特性。
如果overlayfs存储驱动不支持d_type的话,容器在操作文件系统时可能会出现一些奇怪的错误:比如在bootstrap的时候出现Chown error,或者rebuild时发生错误等等。
mkfs.xfs -f -l internal,lazy-count=1,size=128m -i attr=2 -d agcount=8 -i size=512 -n ftype=1 /dev/vdb
journalctl -xeu docker
ln -s /usr/libexec/docker/docker-runc-current /usr/local/bin/docker-runc如果是使用docker 1.13之前的版本,需要做 docker-runc的软链
修改/etc/kubernetes/apiserver文件中KUBEADMISSIONCONTROL参数。
KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"去掉“ServiceAccount”选项。
重启kube-apiserver服务
# systemctl restart kube-apiserver。
修改/etc/kubernetes/apiserver文件中KUBEADMISSIONCONTROL参数。
KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"去掉“SecurityContextDeny”选项。
重启kube-apiserver服务
# systemctl restart kube-apiserver。
注意到kube-apiserver的选项–insecure-port=0,也就是说kubeadm 1.6.0初始化的集群,kube-apiserver没有监听默认的http 8080端口。
所以我们使用kubectl get nodes会报
The connection to the server localhost:8080 was refused - did you specify the right host or port?。查看kube-apiserver的监听端口可以看到只监听了https的6443端口,
为了使用kubectl访问apiserver,在~/.bashprofile中追加下面的环境变量: export KUBECONFIG=/etc/kubernetes/admin.conf source ~/.bashprofile 此时kubectl命令在master node上就好用了
# kubectl get pod # kubectl describe pod通过日志排查,发现没有rhsm,尝试安装yum install rhsm ,不使用redhat的pause镜像,就没有这个问题。
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
kubectl delete clusterrolebinding kubelet-bootstrap [root@k8s-m1 kubernetes]# kubectl get csr -o wide --all-namespaces NAME AGE REQUESTOR CONDITION node-csr-TgFxbCj01ebWz-JQEwrMT5_IAa76Mg5GqgYdPvp2dT8 84s system:bootstrap:c7i6gd Pending
少了角色, 需要加角色
kubectl create clusterrolebinding kubelet-nodes --clusterrole=system:node --group=system:nodes
基于安全性考虑,CSR approving controllers 不会自动 approve kubelet server 证书签名请求,需要手动 approve:
kubectl certificate approve node-csr-TgFxbCj01ebWz-JQEwrMT5_IAa76Mg5GqgYdPvp2dT8
检查/etc/resolve.conf,检查master是否能够连通?
journalctl -xeu kubelet
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl apply -f kube-flannel.yml或者运行kube-router
kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kube-router-all-service-daemonset.yaml
kubectl get pods -o wide --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system kube-router-pn5mn 0/1 CrashLoopBackOff 3 2m34s 192.168.13.136 k8s-n2 <none> <none> [root@k8s-m1 kube-router]# kubectl -n kube-system logs kube-router-pn5mn Failed to parse kube-router config: Failed to build configuration from CLI: Error loading config file "/var/lib/kube-router/kubeconfig": read /var/lib/kube-router/kubeconfig: is a directory
rm -rf /var/lib/kube-router/kubeconfig && touch /var/lib/kube-router/kubeconfig
在kubelet中追加配置
--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice
–runtime-cgroups=/systemd/system.slice –kubelet-cgroups=/systemd/system.slice
libcontainerd 推荐的 kernel 4.3 以上版本
kernel内核升级到 kernel-ml-5.4.5-1.el7.elrepo.x8664 * 新内核运行容器默认开启了net.ipv4.tcptimestamps,需要关闭
手动安装一下 crictl 软件
升级 systemd : yum update systemd
kubectl delete node 10.31.31.29
kubectl describe pod istio-cleanup-secrets -n istio-system
检查kuber-apiserver启动参数中的token.csv和kubelet启动参数中指定的bootstrap文件bootstrap.kubeconfig中的token值是否一致,此外该token必须为实际数值,不能使用变量代替。
yum install -y socat
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
yum list docker-ce.x86_64 --showduplicates |sort -r
yum install -y --setopt=obsoletes=0 \
docker-ce-17.03.2.ce-1.el7.centos \
docker-ce-selinux-17.03.2.ce-1.el7.centos
kubectl delete node xxx
kubectl label node k8s-m1 cpu=high kubectl label node k8s-n2 cpu=mid kubectl label node k8s-n1 cpu=low ...... spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cpu operator: In values: - high - mid
禁止pod调度到该节点上
kubectl cordon <node>
驱逐该节点上的所有pod
kubectl drain <node>
该命令会删除该节点上的所有Pod(DaemonSet除外),在其他node上重新启动它们,通常当该节点维护完成,启动了kubelet后,再使用
kubectl uncordon <node>
即可将该节点添加到kubernetes集群中。
因此可以在编写kubernetes的yaml文件时添加如下内容,即可以将所有docker的时区配置为想要的
......
volumeMounts:
- name: tz-config
mountPath: /etc/localtime
......
volumes:
- name: tz-config
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
创建tiller用户角色
apiVersion: v1 kind: ServiceAccount metadata: name: tiller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: tiller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller namespace: kube-system
删除旧的tiller-deploy
kubectl delete deployment tiller-deploy --namespace=kube-system kubectl delete svc tiller-deploy --namespace=kube-system
重新初始化Helm并指定要使用的 Service Account
$ helm init --service-account tiller
local volume, 这是一个很新的存储类型,建议在k8s v1.10+以上的版本中使用。该local volume类型目前还只是beta版。
Local volume 允许用户通过标准PVC接口以简单且可移植的方式访问node节点的本地存储。 PV的定义中需要包含描述节点亲和性的信息,k8s系统则使用该信息将容器调度到正确的node节点。
--- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-path provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer --- apiVersion: v1 kind: PersistentVolume metadata: name: local-storage spec: capacity: storage: 1Gi # volumeMode field requires BlockVolume Alpha feature gate to be enabled. volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-m1 - k8s-n2 - k8s-n3
最简单的方法:
--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota,ServiceAccount,NodeRestriction
Kubernetes 1.23 中可以使用 Docker Engine,但如果使用 Docker Engine 作为运行时,kubelet 启动时,会打印一个警告日志。您在 1.23 之前的所有版本中都会看到此警告。dockershim 将在 Kubernetes 1.24 移除。
为了更贴近OCI,k8s又搞了一个轻量级的容器运行时cri-o,所以在k8s“抛弃”dockershim后,可供我们选择的容器运行时有containerd和cri-o