目录

kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。

在Kubernetes的文档Creating a single master cluster with kubeadm中已经给出了目前kubeadm的主要特性已经处于beta状态了,在2018年将进入GA状态,说明kubeadm离可以在生产环境中使用的距离越来越近了。

下面我将介绍一下kubeadm的安装,比起k8s的二进制安装方式,kubeadm的安装门槛较低,更容易上手。

1. 准备工作

1.1 机器准备

准备三台Centos7.x虚拟机,具体配置如下:

IP Role CPU Memory Hostname
192.168.199.231 master >= 2C >= 2G master
192.168.199.232 worker >= 2C >= 2G node1
192.168.199.233 worker >= 2C >= 2G node1

IP 根据你自己宿主机机器网段决定。

1.2 系统配置

1.2.1 主机名及域名解析

  1. # 192.168.199.231上执行
  2. hostnamectl set-hostname master
  3. # 192.168.199.232上执行
  4. hostnamectl set-hostname node1
  5. # 192.168.199.233上执行
  6. hostnamectl set-hostname node2
  7. # 192.168.199.231、192.168.199.232、192.168.199.233三台都执行
  8. cat <<EOF>>/etc/hosts
  9. 192.168.199.231 master
  10. 192.168.199.232 node1
  11. 192.168.199.233 node2
  12. EOF

设置完后,相互ping一下看看网络是否通。如:ping node1

1.2.2 免密登录

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

  1. ## 第一步:在master节点执行,一路回车到底
  2. ssh-keygen -t rsa
  3. ## 第二步:在master节点执行以下三句,然后分别输入对应机器登录密码
  4. ssh-copy-id root@master
  5. ssh-copy-id root@node1
  6. ssh-copy-id root@node2

1.2.3 配置yum源

注意:所有虚拟机都需要执行下面的操作

配置阿里软件源(base和epel):

  1. mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak
  2. wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
  3. mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
  4. mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
  5. wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

最后一句记得回车,配置完过后,可通过命令:

yum repolist

来查看是否配置成功。如果出现如下信息则表示成功:

  • base: mirrors.aliyun.com
  • extras: mirrors.aliyun.com
  • updates: mirrors.aliyun.com

配置国内Kubernetes源:

  1. cat <<EOF > /etc/yum.repos.d/kubernetes.repo
  2. [kubernetes]
  3. name=Kubernetes
  4. baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
  5. enabled=1
  6. gpgcheck=1
  7. repo_gpgcheck=1
  8. gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
  9. EOF

配置docker源:

  1. wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

执行清理和更新:

  1. yum clean all && yum makecache && yum update -y # 第一次需要比较久的时间,去喝杯水休息休息

1.2.4 安装必要依赖包

在三台机器上执行命令:

  1. yum install -y epel-release
  2. yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget
  3. /usr/sbin/modprobe ip_vs # 这一句记得回车

ipvs 依赖 ipset

ntp 保证各机器系统时间同步;

1.2.5 关闭防火墙、SELinux、Swap分区

注意:所有虚拟机都需要执行下面的操作

关闭防火墙:

  1. systemctl stop firewalld &&
  2. systemctl disable firewalld &&
  3. iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat &&
  4. iptables -P FORWARD ACCEPT

关闭SELinux:

  1. setenforce 0
  2. sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

关闭Swap分区:

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

1.2.6 配置内核参数

注意:所有虚拟机都需要执行下面的操作

将桥接的IPv4流量传递到iptables的链,swappiness参数调整:

  1. cat <<EOF > /etc/sysctl.d/k8s.conf
  2. net.bridge.bridge-nf-call-ip6tables = 1
  3. net.bridge.bridge-nf-call-iptables = 1
  4. net.ipv4.ip_forward=1
  5. net.ipv4.tcp_tw_recycle=0
  6. vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
  7. vm.overcommit_memory=1 # 不检查物理内存是否够用
  8. vm.panic_on_oom=0 # 开启 OOM
  9. EOF
  10. modprobe ip_vs_rr
  11. modprobe br_netfilter
  12. sysctl --system # 记得回车

2. 安装Docker

2.1 安装

Kubernetes从1.6开始使用CRI(Container Runtime Interface)容器运行时接口。默认的容器运行时仍然是Docker,使用的是kubelet中内置dockershim CRI实现。

查看版本:

  1. # 查看docker版本
  2. yum list docker-ce.x86_64 --showduplicates | sort -r
  3. # 查看docker cli版本
  4. yum list docker-ce-cli.x86_64 --showduplicates |sort -r

Kubernetes 1.15已经针对Docker的1.13.1, 17.03, 17.06, 17.09, 18.06,18.09等版本做了验证,需要注意Kubernetes 1.15最低支持的Docker版本是1.13.1。 我们这里在各节点安装docker的19.03.9版本。

  1. # 安装docker、docker-cli
  2. yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7
  3. # 开机启动 && 启动docker
  4. systemctl enable docker && systemctl start docker
  5. # 查看版本
  6. docker --version

安装docker还可以通过脚本,详情见:https://leisure.wang/procedural-framework/docker/112.html

2.2 配置镜像加速

  1. # 第一步:创建目录(不存在则创建)
  2. mkdir -p /etc/docker
  3. # 第二步:创建并配置daemon.json文件
  4. cat > /etc/docker/daemon.json <<EOF
  5. {
  6. "registry-mirrors": [
  7. "https://registry.docker-cn.com",
  8. "https://hub-mirror.c.163.com",
  9. "https://docker.mirrors.ustc.edu.cn"
  10. ],
  11. "exec-opts": ["native.cgroupdriver=systemd"],
  12. "log-driver": "json-file",
  13. "log-opts": {
  14. "max-size": "100m",
  15. "max-file": "5"
  16. }
  17. }
  18. EOF
  19. # 第三步:重新加载配置并重启docker
  20. systemctl daemon-reload && systemctl restart docker

确认一下iptables filter表中FOWARD链的默认策略(pllicy)为ACCEPT:

  1. # 命令
  2. iptables -nvL
  3. # 结果部分如下:
  4. Chain INPUT (policy ACCEPT 321 packets, 18442 bytes)
  5. pkts bytes target prot opt in out source destination
  6. Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
  7. pkts bytes target prot opt in out source destination
  8. 0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
  9. 0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
  10. 0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
  11. 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
  12. 0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
  13. 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0

3. 使用kubeadm部署k8s集群

3.1 安装kubeadm、kubelet、kubectl

需要在每台机器上都安装以下的软件包:

  • Kubelet:负责与其他节点集群通信,并进行本节点Pod和容器生命周期的管理。
  • Kubeadm:是Kubernetes的自动化部署工具,降低了部署难度,提高效率。
  • Kubectl:是Kubernetes集群管理工具。

查看可用版本:

  1. yum list --showduplicates | grep 'kubeadm\|kubectl\|kubelet'

选择安装kubeadm1.18.0、kubelet1.18.0、kubectl1.18.0

  1. # 安装
  2. yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 --disableexcludes=kubernetes
  3. # 此时还不能启动kubelet,先设置开机启动
  4. systemctl enable --now kubelet

从安装结果可以看出还安装了cri-tools, kubernetes-cni, socat三个依赖:

  • socat是kubelet的依赖
  • cri-tools是CRI(Container Runtime Interface)容器运行时接口的命令行工具

运行kubelet –help可以看到原来kubelet的绝大多数命令行flag参数都被DEPRECATED了。

而官方推荐我们使用–config指定配置文件,并在配置文件中指定原来这些flag所配置的内容。具体内容可以查看这里Set Kubelet parameters via a config file。这也是Kubernetes为了支持动态Kubelet配置(Dynamic Kubelet Configuration)才这么做的,参考Reconfigure a Node’s Kubelet in a Live Cluster

kubelet的配置文件必须是json或yaml格式,具体可查看这里

3.2 配置kubeadm

查看kubelet安装了哪些文件:

  1. # 命令
  2. rpm -ql kubelet
  3. # 结果
  4. /etc/kubernetes/manifests # 清单目录
  5. /etc/sysconfig/kubelet # 配置文件
  6. /usr/bin/kubelet # 主程序
  7. /usr/lib/systemd/system/kubelet.service # unit file

在所有虚拟机上修改/etc/sysconfig/kubelet,加入:

  1. # 命令
  2. sed -i "s/KUBELET_EXTRA_ARGS=/KUBELET_EXTRA_ARGS=\"--fail-swap-on=false\"/" /etc/sysconfig/kubelet
  3. # 查看是否修改
  4. cat /etc/sysconfig/kubelet
  5. # 查看结果
  6. KUBELET_EXTRA_ARGS="--fail-swap-on=false"

安装 kubernetes 主要是安装它的各个镜像,而 kubeadm 已经为我们集成好了运行 kubernetes 所需的基本镜像。但由于国内的网络原因,在搭建环境时,无法拉取到这些镜像。此时我们只需要修改为阿里云提供的镜像服务即可解决该问题。

导出配置文件(未修改文件,不可用):

  1. kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

针对kubeadm.yml文件做修改,新增修改处有4个,如下注释位置,做相应修改即可:

  1. apiVersion: kubeadm.k8s.io/v1beta2
  2. bootstrapTokens:
  3. - groups:
  4. - system:bootstrappers:kubeadm:default-node-token
  5. token: abcdef.0123456789abcdef
  6. ttl: 24h0m0s
  7. usages:
  8. - signing
  9. - authentication
  10. kind: InitConfiguration
  11. localAPIEndpoint:
  12. advertiseAddress: 192.168.199.231 # 修改项,更改为master节点IP
  13. bindPort: 6443
  14. nodeRegistration:
  15. criSocket: /var/run/dockershim.sock
  16. name: master
  17. taints:
  18. - effect: NoSchedule
  19. key: node-role.kubernetes.io/master
  20. ---
  21. apiServer:
  22. timeoutForControlPlane: 4m0s
  23. apiVersion: kubeadm.k8s.io/v1beta2
  24. certificatesDir: /etc/kubernetes/pki
  25. clusterName: kubernetes
  26. controlPlaneEndpoint: "" # 新增项
  27. controllerManager: {}
  28. dns:
  29. type: CoreDNS
  30. etcd:
  31. local:
  32. dataDir: /var/lib/etcd
  33. imageRepository: registry.aliyuncs.com/google_containers # 修改项,修改为阿里云镜像仓库
  34. kind: ClusterConfiguration
  35. kubernetesVersion: v1.18.0
  36. networking:
  37. dnsDomain: cluster.local
  38. podSubnet: "10.244.0.0/16" # 新增项,配置Flannel的默认网段
  39. serviceSubnet: 10.96.0.0/12
  40. scheduler: {}
  41. ---
  42. # 新增项start:开启IPVS模式
  43. apiVersion: kubeproxy.config.k8s.io/v1alpha1
  44. kind: KubeProxyConfiguration
  45. featureGates:
  46. SupportIPVSProxyMode: true
  47. mode: ipvs
  48. # 新增项end:开启IPVS模式

配置修改好后,将配置文件复制到node1、node2备用:

  1. scp kubeadm.yml root@node1:/root
  2. scp kubeadm.yml root@node2:/root

查看和拉取镜像:

  1. # 查看所需镜像列表
  2. kubeadm config images list --config kubeadm.yml
  3. # 拉取镜像 (所有机器都执行)
  4. kubeadm config images pull --config kubeadm.yml
  5. # 执行完毕后,通过命令就可以看到镜像了:
  6. docker images

3.3 使用kubeadm 配置master 节点

注意:在master执行下面的操作

3.3.1 安装 kubernetes 主节点

执行以下命令初始化主节点,该命令指定了初始化时需要使用的配置文件,其中添加 --experimental-upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志。

  1. # 初始化命令
  2. kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log
  3. # 成功则返回如下信息:
  4. Your Kubernetes control-plane has initialized successfully!
  5. To start using your cluster, you need to run the following as a regular user:
  6. mkdir -p $HOME/.kube
  7. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  8. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  9. You should now deploy a pod network to the cluster.
  10. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  11. https://kubernetes.io/docs/concepts/cluster-administration/addons/
  12. Then you can join any number of worker nodes by running the following on each as root:
  13. kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
  14. --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

node1、node2想要加入集群,需要执行上一步返回结果中的命令:

  1. kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
  2. --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

--token:加入集群的token

--discovery-token-ca-cert-hash:发现token证书hash

此时还无法通过命令kubectl get nodes查看节点信息,需要等下面的配置。

如果忘记了加入集群的命令怎么办呢?通过下面两个方法获取token和discovery-token-ca-cert-hash,然后按照上面的命令的格式拼接起来即可。

获取Token,可以在 Master 上输入以下命令查看:

  1. kubeadm token list

默认情况下 Token 过期是时间是24小时,如果 Token 过期以后,可以输入以下命令,生成新的 Token:

  1. kubeadm token create

获取discovery-token-ca-cert-hash 的方法,在 Master 运行以下命令查看:

  1. openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

注意:如果安装 kubernetes 版本和下载的镜像版本不统一则会出现 timed out waiting for the condition 错误。中途失败或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。

3.3.2 配置 kubectl

执行初始化集群时候输出结果中的命令:

  1. mkdir -p $HOME/.kube
  2. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  3. # 非root用户执行
  4. sudo chown $(id -u):$(id -g) $HOME/.kube/config

验证是否成功:

  1. # 命令
  2. kubectl get nodes
  3. # 结果
  4. NAME STATUS ROLES AGE VERSION
  5. master NotReady master 18m v1.18.0
  6. node1 NotReady <none> 14m v1.18.0
  7. node2 NotReady <none> 14m v1.18.0

至此主机诶单配置完成。

3.3.3 kubeadm init执行过程

  • init:指定版本进行初始化操作
  • preflight:初始化前的检查和下载所需要的 Docker 镜像文件
  • kubelet-start:生成 kubelet 的配置文件 var/lib/kubelet/config.yaml,没有这个文件 kubelet 无法启动,所以初始化之前的 kubelet 实际上启动不会成功
  • certificates:生成 Kubernetes 使用的证书,存放在 /etc/kubernetes/pki 目录中
  • kubeconfig:生成 KubeConfig 文件,存放在 /etc/kubernetes 目录中,组件之间通信需要使用对应文件
  • control-plane:使用 /etc/kubernetes/manifest 目录下的 YAML 文件,安装 Master 组件
  • etcd:使用 /etc/kubernetes/manifest/etcd.yaml 安装 Etcd 服务
  • wait-control-plane:等待 control-plan 部署的 Master 组件启动
  • apiclient:检查 Master 组件服务状态。
  • uploadconfig:更新配置
  • kubelet:使用 configMap 配置 kubelet
  • patchnode:更新 CNI 信息到 Node 上,通过注释的方式记录
  • mark-control-plane:为当前节点打标签,打了角色 Master,和不可调度标签,这样默认就不会使用 Master 节点来运行 Pod
  • bootstrap-token:生成 token 记录下来,后边使用 kubeadm join 往集群中添加节点时会用到
  • addons:安装附加组件 CoreDNS 和 kube-proxy

3.4 使用kubeadm配置 worker 节点

3.4.1 将worker加入到集群

将 worker节点加入到集群中很简单,上一步也做了介绍,只需要执行init返回结果中的命令:

  1. kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
  2. --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

3.4.2 验证是否成功

在master节点上运行:

  1. # 命令
  2. kubectl get cs,nodes
  3. # 结果
  4. NAME STATUS MESSAGE ERROR
  5. componentstatus/scheduler Healthy ok
  6. componentstatus/controller-manager Healthy ok
  7. componentstatus/etcd-0 Healthy {"health":"true"}
  8. NAME STATUS ROLES AGE VERSION
  9. node/master NotReady master 84m v1.18.0
  10. node/node1 NotReady <none> 80m v1.18.0
  11. node/node2 NotReady <none> 79m v1.18.0

如果 worker节点加入 master 时配置有问题可以在 worker节点上使用 kubeadm reset 重置配置再使用 kubeadm join 命令重新加入即可。希望在 master 节点删除 node ,可以使用 kubeadm delete nodes 删除。

3.4.3 查看 pod 状态

  1. # 在master上运行
  2. kubectl get pod -n kube-system -o wide
  3. # 结果
  4. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  5. coredns-7ff77c879f-k94rw 0/1 Pending 0 86m <none> <none> <none> <none>
  6. coredns-7ff77c879f-whhdf 0/1 Pending 0 86m <none> <none> <none> <none>
  7. etcd-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
  8. kube-apiserver-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
  9. kube-controller-manager-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
  10. kube-proxy-8jvj5 1/1 Running 1 86m 192.168.199.231 master <none> <none>
  11. kube-proxy-hm8cx 1/1 Running 1 82m 192.168.199.232 node1 <none> <none>
  12. kube-proxy-psnc9 1/1 Running 1 82m 192.168.199.233 node2 <none> <none>
  13. kube-scheduler-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>

由此可以看出 coredns 尚未运行,此时我们还需要安装网络插件。

3.5 配置网络

Kubernetes 中可选的 CNI 插件如下:

  • Flannel
  • Calico
  • Canal
  • Weave

3.5.1 安装flannel网络

  1. # 下载kube-flannel.yml文件,如果无法下载请在附件中获取。
  2. curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
  3. # 安装
  4. kubectl apply -f kube-flannel.yml

3.5.2 配置网卡名称(可选)

如果Node有多个网卡的话,参考flannel issues 39701,目前需要在kube-flannel.yml中使用–iface参数指定集群主机内网网卡的名称,否则可能会出现dns无法解析。需要将kube-flannel.yml下载到本地,flanneld启动参数加上–iface=,网卡名称可通过ip address命令获取,格式为ensXX

  1. # 部分内容
  2. ......
  3. containers:
  4. - name: kube-flannel
  5. image: quay.io/coreos/flannel:v0.11.0-amd64
  6. command:
  7. - /opt/bin/flanneld
  8. args:
  9. - --ip-masq
  10. - --kube-subnet-mgr
  11. - --iface=ens32
  12. ......

3.5.3 查看Pod状态

使用kubectl get pod –all-namespaces -o wide确保所有的Pod都处于Running状态:

  1. # 命令
  2. watch kubectl get pod --all-namespaces -o wide
  3. # 结果(需要等待所有状态为Running,时间可能需要3-5分钟)
  4. NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  5. kube-system coredns-7ff77c879f-k94rw 1/1 Running 0 126m 10.244.0.3 master <none> <none>
  6. kube-system coredns-7ff77c879f-whhdf 1/1 Running 0 126m 10.244.0.2 master <none> <none>
  7. kube-system etcd-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
  8. kube-system kube-apiserver-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
  9. kube-system kube-controller-manager-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
  10. kube-system kube-flannel-ds-amd64-6rcjk 1/1 Running 0 15m 192.168.199.231 master <none> <none>
  11. kube-system kube-flannel-ds-amd64-n464m 1/1 Running 0 15m 192.168.199.232 node1 <none> <none>
  12. kube-system kube-flannel-ds-amd64-rlghv 1/1 Running 0 15m 192.168.199.233 node2 <none> <none>
  13. kube-system kube-proxy-8jvj5 1/1 Running 1 126m 192.168.199.231 master <none> <none>
  14. kube-system kube-proxy-hm8cx 1/1 Running 1 122m 192.168.199.232 node1 <none> <none>
  15. kube-system kube-proxy-psnc9 1/1 Running 1 121m 192.168.199.233 node2 <none> <none>
  16. kube-system kube-scheduler-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>

至此基本环节已经部署完毕,如果没有问题,就可以展开k8s的学习之旅了。

3.5.4 问题处理(可选)

3.5.4.1 解决 ImagePullBackOff

在使用 watch kubectl get pods --all-namespaces 命令观察 Pods 状态时如果出现 ImagePullBackOff 无法 Running 的情况,请尝试使用如下步骤处理:

  • Master 中删除 Nodes:kubectl delete nodes
  • worker中重置配置:kubeadm reset
  • worker重启计算机:reboot
  • worker重新加入集群:kubeadm join
3.5.4.2 Master节点参与工作负载

出于安全原因,您的群集不会在主服务器上安排pod。如果您希望能够在主服务器上安排pod,例如对于用于开发的单机Kubernetes集群,可以运行以下命令:

  1. # 所有主服务器都安排 pod
  2. kubectl taint nodes --all node-role.kubernetes.io/master-
  3. # 指定节点 master 服务器都安排 pod
  4. kubectl taint nodes <master-hostname> node-role.kubernetes.io/master-
  5. 如:kubectl taint nodes master node-role.kubernetes.io/master-

3.6 验证集群DNS是否可用

3.6.1 新建文件my-nginx.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: my-nginx
  5. spec:
  6. selector:
  7. matchLabels:
  8. app: my-nginx
  9. replicas: 2
  10. template:
  11. metadata:
  12. labels:
  13. app: my-nginx
  14. spec:
  15. containers:
  16. - name: my-nginx
  17. image: nginx:1.7.9
  18. ports:
  19. - containerPort: 80

3.6.2 创建Deployment并生成my-nginx服务

  1. # 创建Deployment
  2. kubectl create -f my-nginx.yaml
  3. # 查看Deployment
  4. kubectl get deploy
  5. # 生成服务
  6. kubectl expose deploy my-nginx
  7. # 查看服务
  8. kubectl get services(或 kubectl get svc
  9. # 结果
  10. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  11. kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h2m
  12. my-nginx ClusterIP 10.110.206.225 <none> 80/TCP 7m34s

3.6.3 创建dnsutils-ds.yml文件

创建另一个 Pod,查看 /etc/resolv.conf 是否包含 kubelet 配置的 --cluster-dns 和 --cluster-domain,是否能够将服务 my-nginx 解析到对应的 Cluster IP 10.110.206.225

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: dnsutils-ds
  5. labels:
  6. app: dnsutils-ds
  7. spec:
  8. type: NodePort
  9. selector:
  10. app: dnsutils-ds
  11. ports:
  12. - name: http
  13. port: 80
  14. targetPort: 80
  15. ---
  16. apiVersion: apps/v1
  17. kind: DaemonSet
  18. metadata:
  19. name: dnsutils-ds
  20. labels:
  21. addonmanager.kubernetes.io/mode: Reconcile
  22. spec:
  23. selector:
  24. matchLabels:
  25. app: dnsutils-ds
  26. template:
  27. metadata:
  28. labels:
  29. app: dnsutils-ds
  30. spec:
  31. containers:
  32. - name: my-dnsutils
  33. image: tutum/dnsutils:latest
  34. command:
  35. - sleep
  36. - "3600"
  37. ports:
  38. - containerPort: 80

3.6.4 创建pod dnsutils-ds

  1. kubectl create -f dnsutils-ds.yml

3.6.5 查看pod节点

  1. # 命令
  2. kubectl get pods
  3. # 结果
  4. NAME READY STATUS RESTARTS AGE
  5. curl 0/1 CrashLoopBackOff 13 46m
  6. dnsutils-ds-2xgtq 1/1 Running 0 103s
  7. dnsutils-ds-dvzjm 1/1 Running 0 103s
  8. dnsutils-ds-xtsvz 1/1 Running 0 103s
  9. my-nginx-5c7d476867-sqpjv 1/1 Running 0 19m
  10. my-nginx-5c7d476867-vv57z 1/1 Running 0 19m

3.6.6 开始验证DNS

  1. # 命令
  2. kubectl exec dnsutils-ds-2xgtq -- nslookup my-nginx
  3. # 结果
  4. Server: 10.96.0.10
  5. Address: 10.96.0.10#53
  6. Name: my-nginx.default.svc.cluster.local
  7. Address: 10.110.206.225

从结果看Address: 10.110.206.225已经成功了。

另外,解析外部域名时,需要以 . 结尾:

  1. # 命令
  2. kubectl exec dnsutils-ds-2xgtq -- nslookup leisure.wang.
  3. # 结果
  4. Server: 10.96.0.10
  5. Address: 10.96.0.10#53
  6. Non-authoritative answer:
  7. Name: leisure.wang
  8. Address: 121.36.158.21

3.7 从集群中删除Node

如果需要从集群中移除node2这个Node执行下面的命令:

在master节点上执行:

  1. kubectl drain node2 --delete-local-data --force --ignore-daemonsets
  2. kubectl delete node node2

在 Node 被删除,需要重启所有 kubeadm 安装状态:

  1. kubeadm reset
  2. # 如果要完全删除,请执行下面的清理命令
  3. ifconfig cni0 down
  4. ip link delete cni0
  5. ifconfig flannel.1 down
  6. ip link delete flannel.1
  7. rm -rf /var/lib/cni/

3.8 解决apiserver访问时匿名用户禁用问题

浏览器访问 kube-apiserver 的安全端口 6443 时,提示:

  1. {
  2. "kind": "Status",
  3. "apiVersion": "v1",
  4. "metadata": {
  5. },
  6. "status": "Failure",
  7. "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  8. "reason": "Forbidden",
  9. "details": {
  10. },
  11. "code": 403
  12. }

对于正式环境,需要创建一个用户并授权,在上面二进制二进制安装里介绍过,多少还是烦了点。

对于学习环境,我们不需要那么麻烦,不就是匿名用户被禁用了吗,直接给匿名用户授权就可以了。

解决办法:绑定一个cluster-admin的权限

  1. kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous

4. 部署whoami

whoami 是一个简单的HTTP docker服务,用于打印容器ID

在 Master 运行部署 Whoami:

  1. kubectl create deployment whoami --image=idoall/whoami

查看 Whoami 部署状态:

  1. kubectl get deployments

查看 Whoami 的部署信息:

  1. kubectl describe deployment whoami

查看 Whoami 的pod信息:

  1. kubectl describe pod whoami

为 Whoami 扩展端口;创建一个可以通过互联网访问的 Whoami 容器:

  1. kubectl create service nodeport whoami --tcp=80:80

[本文由https://leisure.wang/整理提供]

上面的命令将在主机上为 Whoami 部署创建面向公众的服务。

由于这是一个节点端口部署,因此 kubernetes 会将此服务分配给32000+范围内的主机上的端口。

查看当前的服务状态:

  1. # 命令
  2. kubectl get svc,pods -o wide
  3. # 结果
  4. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
  5. service/dnsutils-ds NodePort 10.97.94.13 <none> 80:30157/TCP 37m app=dnsutils-ds
  6. service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h45m <none>
  7. service/my-nginx ClusterIP 10.110.206.225 <none> 80/TCP 51m app=my-nginx
  8. service/whoami NodePort 10.108.27.255 <none> 80:32729/TCP 29s app=whoami
  9. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  10. pod/curl 0/1 CrashLoopBackOff 20 82m 10.244.1.2 node1 <none> <none>
  11. pod/dnsutils-ds-2xgtq 1/1 Running 0 37m 10.244.1.4 node1 <none> <none>
  12. pod/dnsutils-ds-dvzjm 1/1 Running 0 37m 10.244.0.4 master <none> <none>
  13. pod/dnsutils-ds-xtsvz 1/1 Running 0 37m 10.244.2.3 node2 <none> <none>
  14. pod/my-nginx-5c7d476867-sqpjv 1/1 Running 0 55m 10.244.1.3 node1 <none> <none>
  15. pod/my-nginx-5c7d476867-vv57z 1/1 Running 0 55m 10.244.2.2 node2 <none> <none>
  16. pod/whoami-7976c8ddf6-9lbcp 1/1 Running 0 5m13s 10.244.2.4 node2 <none> <none>

上面的服务可以看到 Whoami 运行在 32729 端口。

测试 Whoami 服务是否运行正常:

  1. # 命令
  2. curl node1:32729
  3. # 结果
  4. [mshk.top]I'm whoami-7976c8ddf6-9lbcp

扩展部署应用:

  1. kubectl scale --replicas=3 deployment/whoami

查看扩展后的结果,可以看到 Whoami 在 master、node1、node2上面都有部署

ClusterIP 模式会提供一个集群内部的虚拟IP(与Pod不在同一网段),以供集群内部的 Pod 之间通信使用。

删除 Whoami 部署:

  1. kubectl delete deployment whoami
  2. kubectl delete service whoami

5. 部署Dashboard

Kubernetes Dashboard 是 Kubernetes 集群的 Web UI,用于管理集群。

5.1 安装

注:在master节点上进行如下操作

5.1.0 下载配置文件

由于网络原因,可能无法下载,无法下载则请直接使用5.1.1文件内容

  1. wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

如果下载成功,请参照5.1.1做如下修改:

  1. 修改镜像地址为阿里云
  2. 修改类型为 NodePort 访问(无type则新增)
  3. 设置端口号为 30001

5.1.1 创建文件kubernetes-dashboard.yaml

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. labels:
  5. k8s-app: kubernetes-dashboard
  6. name: kubernetes-dashboard-certs
  7. namespace: kube-system
  8. type: Opaque
  9. ---
  10. apiVersion: v1
  11. kind: ServiceAccount
  12. metadata:
  13. labels:
  14. k8s-app: kubernetes-dashboard
  15. name: kubernetes-dashboard
  16. namespace: kube-system
  17. ---
  18. kind: Role
  19. apiVersion: rbac.authorization.k8s.io/v1
  20. metadata:
  21. name: kubernetes-dashboard-minimal
  22. namespace: kube-system
  23. rules:
  24. - apiGroups: [""]
  25. resources: ["secrets"]
  26. verbs: ["create"]
  27. - apiGroups: [""]
  28. resources: ["configmaps"]
  29. verbs: ["create"]
  30. - apiGroups: [""]
  31. resources: ["secrets"]
  32. resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  33. verbs: ["get", "update", "delete"]
  34. - apiGroups: [""]
  35. resources: ["configmaps"]
  36. resourceNames: ["kubernetes-dashboard-settings"]
  37. verbs: ["get", "update"]
  38. - apiGroups: [""]
  39. resources: ["services"]
  40. resourceNames: ["heapster"]
  41. verbs: ["proxy"]
  42. - apiGroups: [""]
  43. resources: ["services/proxy"]
  44. resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  45. verbs: ["get"]
  46. ---
  47. apiVersion: rbac.authorization.k8s.io/v1
  48. kind: ClusterRoleBinding
  49. metadata:
  50. name: kubernetes-dashboard-minimal
  51. namespace: kube-system
  52. roleRef:
  53. apiGroup: rbac.authorization.k8s.io
  54. kind: ClusterRole
  55. name: cluster-admin
  56. subjects:
  57. - kind: ServiceAccount
  58. name: kubernetes-dashboard
  59. namespace: kube-system
  60. ---
  61. kind: Deployment
  62. apiVersion: apps/v1
  63. metadata:
  64. labels:
  65. k8s-app: kubernetes-dashboard
  66. name: kubernetes-dashboard
  67. namespace: kube-system
  68. spec:
  69. replicas: 1
  70. revisionHistoryLimit: 10
  71. selector:
  72. matchLabels:
  73. k8s-app: kubernetes-dashboard
  74. template:
  75. metadata:
  76. labels:
  77. k8s-app: kubernetes-dashboard
  78. spec:
  79. containers:
  80. - name: kubernetes-dashboard
  81. image: registry.aliyuncs.com/google_containers/kubernetes-dashboard-amd64:v1.10.1 # 修改镜像地址为阿里云
  82. ports:
  83. - containerPort: 8443
  84. protocol: TCP
  85. args:
  86. - --auto-generate-certificates
  87. volumeMounts:
  88. - name: kubernetes-dashboard-certs
  89. mountPath: /certs
  90. - mountPath: /tmp
  91. name: tmp-volume
  92. livenessProbe:
  93. httpGet:
  94. scheme: HTTPS
  95. path: /
  96. port: 8443
  97. initialDelaySeconds: 30
  98. timeoutSeconds: 30
  99. volumes:
  100. - name: kubernetes-dashboard-certs
  101. secret:
  102. secretName: kubernetes-dashboard-certs
  103. - name: tmp-volume
  104. emptyDir: {}
  105. serviceAccountName: kubernetes-dashboard
  106. tolerations:
  107. - key: node-role.kubernetes.io/master
  108. effect: NoSchedule
  109. ---
  110. kind: Service
  111. apiVersion: v1
  112. metadata:
  113. labels:
  114. k8s-app: kubernetes-dashboard
  115. name: kubernetes-dashboard
  116. namespace: kube-system
  117. spec:
  118. type: NodePort # 修改类型为 NodePort 访问(无type则新增)
  119. ports:
  120. - port: 443
  121. targetPort: 8443
  122. nodePort: 30001 # 设置端口号为 30001
  123. selector:
  124. k8s-app: kubernetes-dashboard

5.1.2 部署

  1. kubectl create -f kubernetes-dashboard.yaml

5.1.3 查看

  1. kubectl -n kube-system get pods
  2. kubectl -n kube-system get service kubernetes-dashboard
  3. kubectl -n kube-system describe service kubernetes-dashboard

5.2 访问

需要使用 NodeIP:30001(如:https://192.168.199.231:30001/) 访问 Dashboard,因为证书原因除火狐浏览器外其它浏览器无法直接打开页面。

作为学习,暂时可以不用在意这些细节。访问后,在火狐里点击高级>接受风险并继续。

此时将会看到“Kubernetes 仪表板”。

5.3 登录

5.3.1 kubeconfig方式

该config文件位置一般是 ~/.kube/config(Master节点),只要将该文件下载到本地机器上,登录的时候选择它就行了。

5.3.2 令牌方式

创建访问Dashboard的token,需要创建一个 Admin 用户并授予 Admin 角色绑定,使用下面的 yaml文件 创建 admin 用户并赋予管理员权限,然后可以通过 Token 访问 kubernetes。

创建 kubernetes-dashboard-admin.yaml 文件:

  1. apiVersion: rbac.authorization.k8s.io/v1beta1
  2. kind: ClusterRoleBinding
  3. metadata:
  4. name: kubernetes-dashboard
  5. labels:
  6. k8s-app: kubernetes-dashboard
  7. roleRef:
  8. apiGroup: rbac.authorization.k8s.io
  9. kind: ClusterRole
  10. name: cluster-admin
  11. subjects:
  12. - kind: ServiceAccount
  13. name: kubernetes-dashboard
  14. namespace: kube-system

执行部署:

  1. kubectl apply -f kubernetes-dashboard-admin.yaml

获取secret中的token值:

  1. kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token
  2. # 记得替换成你自己的secret资源名
  3. kubectl -n kube-system describe secret kubernetes-dashboard-token-bsjtr

也可以通过 jsonpath 直接获取 token:

  1. kubectl -n kube-system get secret kubernetes-dashboard-token-bsjtr -o jsonpath={.data.token}|base64 -d

也可以使用下面的命令,直接获取 kubernetes-dashboard-token 的值,然后直接打印输出:

  1. k8tokenvalue=`kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token | awk '{print $2}'`;kubectl -n kube-system get secret $k8tokenvalue -o jsonpath={.data.token}|base64 -d | awk '{print $1}'

注意:下面的获取token值的方式和上面三种方式选择一种即可。

您还可以通过kubectl create clusterrolebinding的方式来授予 Dashboard 服务 Admin 管理员权限:

  1. kubectl create serviceaccount dashboard-admin -n kube-system
  2. kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
  3. kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

登录成功后就能看到后台页面了:

6. Weave Scope 监控集群

创建 Kubernetes 集群并部署容器化应用只是第一步。一旦集群运行起来,我们需要确保一起正常,所有必要组件就位并各司其职,有足够的资源满足应用的需求。Kubernetes 是一个复杂系统,运维团队需要有一套工具帮助他们获知集群的实时状态,并为故障排查提供及时和准确的数据支持。

6.1 安装

Weave Scope 是 Docker 和 Kubernetes 可视化监控工具。Scope 提供了至上而下的集群基础设施和应用的完整视图,用户可以轻松对分布式的容器化应用进行实时监控和问题诊断。

在 K8s 集群中安装 Scope 的方法很简单,使用下面的命令:

  1. # 命令
  2. kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '\n')&k8s-service-type=NodePort"
  3. # 结果
  4. service-type=NodePort"
  5. namespace/weave created
  6. serviceaccount/weave-scope created
  7. clusterrole.rbac.authorization.k8s.io/weave-scope created
  8. clusterrolebinding.rbac.authorization.k8s.io/weave-scope created
  9. deployment.apps/weave-scope-app created
  10. service/weave-scope-app created
  11. deployment.apps/weave-scope-cluster-agent created
  12. daemonset.apps/weave-scope-agent created

部署成功后有如下组件:

  1. # 命令
  2. kubectl get pod -n weave
  3. # 结果
  4. NAME READY STATUS RESTARTS AGE
  5. weave-scope-agent-2t7z2 0/1 ContainerCreating 0 60s
  6. weave-scope-agent-ll9r9 0/1 ContainerCreating 0 60s
  7. weave-scope-agent-qzp2b 0/1 ContainerCreating 0 60s
  8. weave-scope-app-bc7444d59-lznk8 0/1 ContainerCreating 0 62s
  9. weave-scope-cluster-agent-7944c858c9-ms7mz 0/1 ContainerCreating 0 61s
  10. # 命令
  11. kubectl get svc -n weave
  12. # 结果
  13. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  14. weave-scope-app NodePort 10.108.61.84 <none> 80:30286/TCP 3m9s
  15. # 命令
  16. kubectl get deploy -n weave
  17. # 结果
  18. NAME READY UP-TO-DATE AVAILABLE AGE
  19. weave-scope-app 1/1 1 1 4m19s
  20. weave-scope-cluster-agent 1/1 1 1 4m18s
  • DaemonSet weave-scope-agent,集群每个节点上都会运行的 scope agent 程序,负责收集数据。
  • Deployment weave-scope-app,scope 应用,从 agent 获取数据,通过 Web UI 展示并与用户交互。
  • Service weave-scope-app,默认是 ClusterIP 类型,我们已经在上面的命令中添加了参数k8s-service-type=NodePort修改为 NodePort。

6.2 使用Scope

浏览器访问http://MASTER_IP:30286/(端口可在上一步查看命令中获得),cope 默认显示当前所有的 Controller(Deployment、DaemonSet 等)。

6.2.1 拓扑结构

Scope 会自动构建应用和集群的逻辑拓扑。比如点击顶部 Pods,会显示所有 Pod 以及 Pod 之间的依赖关系。

点击 Hosts,会显示各个节点之间的关系,可以在 Scope 中查看资源的 CPU 和内存使用情况。

6.2.2 在线操作

Scope 还提供了便捷的在线操作功能,比如选中某个 Host,点击 >_ 按钮可以直接在浏览器中打开节点的命令行终端:

点击 Deployment 的 + 可以执行 Scale Up 操作:

可以查看 Pod 的日志:

可以 attach、restart、stop 容器,以及直接在 Scope 中排查问题:

6.2.3 强大的搜索功能

Scope 支持关键字搜索和定位资源。

还可以进行条件搜索,比如查找和定位 MEMORY > 1M 的 Containers。

Weave Scope 界面极其友好,操作简洁流畅,更多功能留给大家去探索。

官方文档:https://www.weave.works/docs/scope/latest/installing/#k8s

写在最后

通过kubeadm安装k8s集群环境的介绍就到这里了,书写安装过程难免出现不足的地方,如果出了问题,需要读者多多思考。由于国内网络的原因,文档中所需要的大部分配置文件都已经贴了出来,读者只需要根据自己的机器环境做相应的修改即可。通过kubeadm安装k8s集群环境,相对于二进制的安装方式来说,还是比较简单的,需要多多实践,才能出真知。我是东方雨倾,感谢大家的支持,谢谢!

附件

链接:https://pan.baidu.com/s/1qWdZ_CclTxm2ybE4h8dziA

提取码:ruo5

原文地址:https://leisure.wang/procedural-framework/docker/513.html

还不会K8S吗?先从kubeadm开始吧的更多相关文章

  1. k8s常用指令集(kubectl kubeadm)

    1      Kubectl指令集 1.1      Master查询节点信息 [root@master1 kubernetes-1.10]# kubectl get nodes 1.2      查 ...

  2. k8s踩坑记 - kubeadm join 之 token 失效

    抛砖引玉 环境 centos 7 amd64 两台 kubernetes 1.10 伴随着k8s1.10版本的发布,前天先在一台机器上搭建了k8s单机版集群,即既是master,也是node,按照经验 ...

  3. k8s环境搭建--基于kubeadm方法

    环境 master node: 数量 1, 系统 ubuntu 16.04_amd64 worker node: 数量 1, 系统 ubuntu 16.04_amd64 kubernetes 版本: ...

  4. Kubernetes(K8s) 安装(使用kubeadm安装Kubernetes集群)

    背景: 由于工作发生了一些变动,很长时间没有写博客了. 概述: 这篇文章是为了介绍使用kubeadm安装Kubernetes集群(可以用于生产级别).使用了Centos 7系统. 一.Centos7 ...

  5. [K8s 1.9实践]Kubeadm 1.9 HA 高可用 集群 本地离线镜像部署

    k8s介绍 k8s 发展速度很快,目前很多大的公司容器集群都基于该项目,如京东,腾讯,滴滴,瓜子二手车,北森等等. kubernetes1.9版本发布2017年12月15日,每是那三个月一个迭代, W ...

  6. Kubernetes实战指南(三十三):都0202了,你还在手写k8s的yaml文件?

    目录 1. k8s的yaml文件到底有多复杂 2. 基于图形化的方式自动生成yaml 2.1 k8s图形化管理工具Ratel安装 2.2 使用Ratel创建生成yaml文件 2.2.1 基本配置 2. ...

  7. 使用Kubeadm创建k8s集群之节点部署(三十一)

    前言 本篇部署教程将讲述k8s集群的节点(master和工作节点)部署,请先按照上一篇教程完成节点的准备.本篇教程中的操作全部使用脚本完成,并且对于某些情况(比如镜像拉取问题)还提供了多种解决方案.不 ...

  8. kubeadm部署K8S集群v1.16.3

    本次先更新kubeadm快速安装K8S,二进制安装上次没写文档,后续更新,此次最新的版本是V1.16.3 1.关闭防火墙.关闭selinux.关闭swapoff -a systemctl stop f ...

  9. 使用kubeadm搭建高可用k8s v1.16.3集群

    目录 1.部署环境说明 2.集群架构及部署准备工作 2.1.集群架构说明 2.2.修改hosts及hostname 2.3.其他准备 3.部署keepalived 3.1.安装 3.2.配置 3.3. ...

随机推荐

  1. 初入React源码(一)

    导语 React是我接触的第二个框架,我最初开始接触的是vue,但是并没有深入的理解过vue,然后在工作过程中,我开始使用了React,现在已经觉得React会比vue更加实用,但是这只是个人观点,可 ...

  2. 使用@vue/cli搭建vue项目开发环境

    当前系统版本 mac OS 10.14.2 1.安装node.js开发环境 前端开发框架和环境都是需要 Node.js  vue的运行是要依赖于node的npm的管理工具来实现 <mac OS ...

  3. [译] React 16.3(.0-alpha) 新特性

    原文地址:What's new in React 16.3(.0-alpha) 原文作者:Bartosz Szczeciński 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/ ...

  4. android自定义View&自定义ViewGroup(上)

    一般自定义view需要重写的方法 void onMeasure(int widthMeasureSpec, int heightMeasureSpec) void onSizeChanged(int ...

  5. 解决vue渲染时闪烁{{}}的问题

    原文转自: 点我 Vue页面加载时v-show设置的隐藏元素出现导致页面闪烁问题在写APP社区页面的时候在一些地方用了v-show,在刷新页面的时候就发现即便在逻辑判断为false某些元素不该显示时也 ...

  6. 量子纠错码——Stabilizer codes

    对于错误,一般有两种: random: 错误以一定的概率发生在每个比特上(对这种问题的研究一般是信息论中,信道熵一类的问题) worst case: 错误发生在某个比特上,这也是纠错码襄阳解决的问题 ...

  7. 基础JS遇到的一些题01

    1.两种数组去重方法 const unique = arr =>{ let mySet = new Set(arr); /!* let newArr =[]; for (let i = 0 ;i ...

  8. Coursera课程笔记----计算导论与C语言基础----Week 2

    计算机的历史与未来(Week 2) 计算机历史 早期计算机:手工计算器➡️机械计算器➡️计算机原型 现代计算机:电子管计算机➡️晶体管计算机➡️集成电路计算机➡️超大规模集成电路 早期的手工计算辅助工 ...

  9. 【Scala】isInstanceOf 与 classOf的对比,代码+注解简洁明了

    class Animal { } class Cat extends Animal { } object Cat { def main(args: Array[String]): Unit = { / ...

  10. C# 数据操作系列 - 4. 自己实现一个ORM

    0. 前言 在之前的几篇内容中,我们了解了如何通过ADO.NET 访问数据库,如何修改.新增数据.如何通过DataSet和DataAdapter获取数据,我们将在这一篇试试自己实现一个简单的ORM框架 ...