1. 背景说明

却省情况下,Java运行时根据运行它的用户授予安全权限。当Tomcat以系统管理员身份或作为系统服务运行时,Java运行时取得了系统用户或系统管理员所具有的全部权限。这样一来,Java运行时就取得了所有文件夹中所有文件的全部权限。并且Servlets(JSP在运行过程中要转换成Servlets)取得了同样的权限。所以Java代码可以调用Java SDK中的文件API列出文件夹中的全部文件,删除任何文件,最大的危险在于以系统权限运行一个程序。

2. 实施指导

2.1. 当安装账户为超级管理员时

  1. 专门为Tomcat建立一个单独的用户和用户组。
# groupadd tomcatgroup
# useradd -g tomcatgroup -d /home/tomcat -m tomcatuser

为用户设置密码:

passwd tomcatuser

密码要符合强口令要求(密码至少8位长度,至少包含大写字母、小写字母、数字和特殊字符中的两种)。

注:tomcatgroup和tomcatuser为组名和用户名,用户可根据需要自行修改。

  1. 设置权限。

更改Tomcat安装目录属主为tomcatuser用户;为tomcatuser用户添加应用程序(例如webapps,或者单独放置在tomcat安装目录之外的应用目录)目录的的只读权限;如果某些应用程序需要写权限,请单独为其配置tomcatuser的写权限。

  1. 以tomcatuser用户登录后启动Tomcat服务器。

2.2. 当安装账户为普通用户时

  1. 在安装之前就建立一个单独的用户和用户组。
groupadd tomcatgroup
useradd -g tomcatgroup tomcatuser -p tomcatuser
  1. 使用新建立的tomcatuser安装Tomcat后,不要再使用tomcatuser用户启动运行或安装其它程序;如果产品的Web应用被放置在Tomcat安装目录之外,请为tomcatuser添加该目录的只读权限;如果某些应用程序需要写权限,则单独为其配置tomcatuser的写权限。

1. 消耗内存脚本memory_usage.sh

1.1. Shell代码

#!/bin/bash
# Destription: testing memory usage 
# Example    : sh memory_usage.sh 500M | sh memory_usage.sh 1G | sh memory_usage.sh release

FILE_NAME=`basename $0`
memsize=$2
function usage()
{
echo "Usage:$FILE_NAME consume memory_size|release -----the value of memory_size like 100M 2G and etc"
echo "Example: $FILE_NAME consume 1G"
echo "         $FILE_NAME release"
}
function consume()
{
if [ -d  /tmp/memory ];then
    echo "/tmp/memory already exists"
else
    mkdir /tmp/memory
fi
mount -t tmpfs -o size=$1 tmpfs /tmp/memory   
dd if=/dev/zero of=/tmp/memory/block

}

function release()
{
rm /tmp/memory/block;ret=$?
if [ $ret != 0 ]; then
    echo "remove memory data failed"
    return $ret
fi

umount /tmp/memory;ret=$?
if [ $ret != 0 ]; then
    echo "umount memory filedir failed"
    return $ret
fi

rmdir /tmp/memory;ret=$?
if [ $ret != 0 ]; then
    echo "remove memory filedir failed"
    return $ret
fi

}

function main()
{
case "$1" in
    consume) consume $memsize;;
    release) release;;
          *) usage;exit 1;;
esac
}

main $*

1.2. 使用方法

需要以root权限执行。

sh memory_usage.sh consume {内存大小}

如:

memory_usage.sh consume 1G    # 即消耗1G 的内存

取消内存消耗:

sh memory_usage.sh release

2. 消耗CPU脚本cpu_usage.sh

2.1. Shell代码

#!/bin/bash
# Destription: test cpu usage 
# Example    : sh cpu_usage.sh consume 8 | sh cpu_usage.sh release

FILE_NAME=`basename $0`
cpunum=$2
pid_array=()
function usage()
{
echo "Usage:$FILE_NAME consume cpu_number|release -----the value of cpu_number is an integer,such as 1,2,3"
echo "Example: $FILE_NAME consume 12"
echo "         $FILE_NAME release"
}

function endless_loop()
{
echo -ne "i=0;
while true
do
    i=i+100;
    i=100
done" | /bin/bash &
}

function consume()
{
for i in `seq $1`
do
    endless_loop
    pid_array[$i]=$!
done
echo "consume cpu resources process ids are: ${pid_array[*]}"
}

function release()
{
for pid in $(ps -ef |grep /bin/bash |grep -v grep |awk '{print $2}' |xargs)
do
    kill -9 $pid
done
}

function main()
{
case "$1" in
    consume) consume $cpunum;;
    release) release;;
          *) usage;exit 1;;
esac
}

main $*

2.2. 使用方法

使用之前使用命令先查询下CPU的个数:

cat /proc/cpuinfo | grep "processor"|wc -l

grep processor /proc/cpuinfo |wc -l

需要构造消耗2颗CPU的资源运行脚本:

sh cpu_usage.sh consume 2

此时运行top命令查看CPU的使用率。

如果要释放CPU资源,运行:

sh cpu_usage.sh release

即可释放cpu资源。

连接SSH服务器,使用私钥连接,将比使用密码连接更加安全。

1. 服务器生成密钥对

首先,进入用户家目录:

cd

使用ssh-keygen生成公私钥对:

ssh-keygen -t rsa

过程中可以选择设置密码passphrase或者不设置。

生成后,将在用户家目录下创建.ssh目录,其中包含生成的公私钥对。

其中id_rsa为私钥,id_rsa.pub为公钥。

2. SSH服务器配置

id_rsa.pub名称的公钥的内容导入到~/.ssh/authorized_keys文件中。

cat id_rsa.pub >> ~/.ssh/authorized_keys

3. SSH客户端配置-Windows XShell

id_rsa名称的私钥下载到本地或者复制其内容出来使用,后续将使用该私钥连接到远程服务器。

连接SSH服务器时,选择Public Key(U)方式进行认证,然后将下载的id_rsa文件导入到用户密钥管理器中。

选择『记住密码』,则在后续连接时可以自动连接了。

4. SSH客户端配置-Mac OS终端设置

id_rsa名称的私钥内容拷贝到Mac OS的终端的如下本地私钥文件中,如私钥文件名为private_key_centos_61

本地目录为/Users/harid/.ssh

使用如下命令连接SSH服务器:

ssh root@192.168.3.61 -p 22 -i ~/.ssh/private_key_centos_61

其中-i参数指定本地的私钥文件。

可以将上述命令以别名方式设置到~/.zprofile文件中,以避免每次都需要输入这么长的命令。

5. SSH客户端配置-手机端ConnectBot设置

将下载的id_rsa名称的私钥文件导入到ConnectBot软件中。

导入后,即可编辑连接,设置使用密钥验证

6. 关闭密码认证方式

至此,可以使用私钥进行SSH认证,即可关闭密码认证方式了。

在服务器上,修改/etc/ssh/sshd_config文件内容:

vi /etc/ssh/sshd_config

设置参考如下:

PubkeyAuthentication yes
PasswordAuthentication no

设置完后,重启ssh服务。

service sshd restart

再使用密码登录,将出现:

1. 下载kube-flannel.yaml

wget https://github.com/flannel-io/flannel/releases/download/v0.22.3/kube-flannel.yml

若无法下载,则使用下面的YAML内容:

# kube-flannel.yml
apiVersion: v1
kind: Namespace
metadata:
  labels:
    k8s-app: flannel
    pod-security.kubernetes.io/enforce: privileged
  name: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: flannel
  name: flannel
  namespace: kube-flannel
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: flannel
  name: flannel
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
- apiGroups:
  - networking.k8s.io
  resources:
  - clustercidrs
  verbs:
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: flannel
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-flannel
---
apiVersion: v1
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
kind: ConfigMap
metadata:
  labels:
    app: flannel
    k8s-app: flannel
    tier: node
  name: kube-flannel-cfg
  namespace: kube-flannel
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: flannel
    k8s-app: flannel
    tier: node
  name: kube-flannel-ds
  namespace: kube-flannel
spec:
  selector:
    matchLabels:
      app: flannel
      k8s-app: flannel
  template:
    metadata:
      labels:
        app: flannel
        k8s-app: flannel
        tier: node
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      containers:
      - args:
        - --ip-masq
        - --kube-subnet-mgr
        command:
        - /opt/bin/flanneld
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: EVENT_QUEUE_DEPTH
          value: "5000"
        image: docker.io/flannel/flannel:v0.22.3
        name: kube-flannel
        resources:
          requests:
            cpu: 100m
            memory: 50Mi
        securityContext:
          capabilities:
            add:
            - NET_ADMIN
            - NET_RAW
          privileged: false
        volumeMounts:
        - mountPath: /run/flannel
          name: run
        - mountPath: /etc/kube-flannel/
          name: flannel-cfg
        - mountPath: /run/xtables.lock
          name: xtables-lock
      hostNetwork: true
      initContainers:
      - args:
        - -f
        - /flannel
        - /opt/cni/bin/flannel
        command:
        - cp
        image: docker.io/flannel/flannel-cni-plugin:v1.2.0
        name: install-cni-plugin
        volumeMounts:
        - mountPath: /opt/cni/bin
          name: cni-plugin
      - args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        command:
        - cp
        image: docker.io/flannel/flannel:v0.22.3
        name: install-cni
        volumeMounts:
        - mountPath: /etc/cni/net.d
          name: cni
        - mountPath: /etc/kube-flannel/
          name: flannel-cfg
      priorityClassName: system-node-critical
      serviceAccountName: flannel
      tolerations:
      - effect: NoSchedule
        operator: Exists
      volumes:
      - hostPath:
          path: /run/flannel
        name: run
      - hostPath:
          path: /opt/cni/bin
        name: cni-plugin
      - hostPath:
          path: /etc/cni/net.d
        name: cni
      - configMap:
          name: kube-flannel-cfg
        name: flannel-cfg
      - hostPath:
          path: /run/xtables.lock
          type: FileOrCreate
        name: xtables-lock

2. 应用kube-flannel.yml

执行:

kubectl apply -f kube-flannel.yml

执行如下命令查看所有的Pod:

kubectl get pod -A

1. 设置系统主机名及hosts文件

记得将所有主机的主机名与IP的解析都写入/etc/hosts文件。

2. 更新系统&设置存储库

yum update -y
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

3. 相关设置

3.1. 禁用iptablesfirewalld服务

systemctl stop firewalld

systemctl disable firewalld

systemctl stop iptables

systemctl disable iptables

3.2. 禁用SELinux

sed -i 's/enforcing/disabled/' /etc/selinux/config

3.3. 禁用swap分区

永久关闭swap分区,编辑/etc/fstab文件,将swap行的内容注释掉。

# /dev/mapper/xxx    swap   xxx

3.4. 调整内核参数

/etc/sysctl.d/k8s.conf文件中追加如下三行内容:

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

依次执行如下命令:

sysctl -p
modprobe br_netfilter
lsmod | grep br_netfilter

4. 安装docker和cri-dockerd(所有节点执行)

4.1. 安装docker

  1. 移除旧版docker。
yum remove docker \
       docker-client \
       docker-client-latest \
       docker-common \
       docker-latest \
       docker-latest-logrotate \
       docker-logrotate \
       docker-engine
  1. 安装docker及其依赖库。
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 启动Docker,设置开机自启动。
# 启动docker
systemctl start docker

# 设置docker开机启动
systemctl enable docker

# 验证
systemctl status docker

4.2. 安装cri-dockerd

K8S 1.24版本后需要使用cri-dockerd和docker通信。

  1. 下载cri-dockerd。
# 若没有wget,则执行
yum install -y wget

# 下载
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd-0.3.4-3.el7.x86_64.rpm

# 安装
rpm -ivh cri-dockerd-0.3.4-3.el7.x86_64.rpm

# 重载系统守护进程
systemctl daemon-reload
  1. 设置镜像加速。

Docker Hub 是 Docker 官方提供的一个公开的 Registry,里面存储了很多常用的镜像,当我们使用 Docker 运行容器时,如果本地没有这个镜像,它就会到 Docker Hub 去下载。但是,由于 Docker Hub 服务器在国外,所以在国内下载速度比较慢。而 Registry Mirror 也被称为 Docker 镜像加速器,它实际上就是一个代理服务器,能够提供更快的镜像下载速度。

为了从国内的镜像托管站点获得镜像加速支持,建议修改Docker的配置文件,增加Registry Mirror参数,将镜像配置写入配置参数中。

编辑/etc/docker/daemon.json,设置:

{
  "registry-mirrors": ["https://c12xt3od.mirror.aliyuncs.com"]
}
  1. 修改配置文件/usr/lib/systemd/system/cri-docker.service,修改第10行ExecStart=为:
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9

其中pause:3.9版本是根据K8S的版本相关,当前安装v1.28.2版本的K8S时,通过如下命令得知pause的版本为3.9:

kubeadm config images list --kubernetes-version v1.28.2
  1. 自启动、重启Docker组件。
# 重载系统守护进程
systemctl daemon-reload

# 设置cri-dockerd自启动
systemctl enable cri-docker.socket cri-docker

# 启动cri-dockerd
systemctl start cri-docker.socket cri-docker

# 检查Docker组件状态
systemctl status docker cir-docker.socket cri-docker

5. 安装Kubernetes

5.1. 配置repo源

/etc/yum.repos.d/目录下创建kubernetes.repo文件,内容如下:

[kubernetes]
name=Kubernetes Repository
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

5.2. 安装kubectl&kubelet&kubeadm

执行如下命令安装:

yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

5.3. 检查runc

执行:

runc -v

6. Node节点加入集群

6.1. 环境配置

  1. 将Master节点的/etc/kubernetes/admin.conf文件拷贝到Node节点的/etc/kubernetes/目录下。

  1. 将admin.conf加入环境变量,直接使用永久生效。
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >>  ~/.bash_profile
source ~/.bash_profile

6.2. 加入集群

  1. 在Master节点执行kubeadm init成功后,会出现kubeadm join xxx xxx的命令,直接复制到Node节点执行就好。
  2. 若没有复制到kubeadm join的命令或者是想要在集群中加入新节点,则先在Master执行如下命令,获取token 和 discovery-token-ca-cert-hash。
    1. 获取 token 参数
kubeadm token list   # 查看已有 token
kubeadm token create # 没有token则执行,创建新的 TOKEN

  1. 获取 discovery-token-ca-cert-hash 参数
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null |  openssl dgst -sha256 -hex | sed 's/^.* //'

  1. 修改获取的 token 和 discovery-token-ca-cert-hash 后,再在Node节点执行:
kubeadm join 192.168.3.61:6443 --token dz3s8l.8co7h567py8kbr1n --discovery-token-ca-cert-hash sha256:a7f52953d123a1c7fc6ccdb0ee6c0f0b0c52dbb06ea8592d3f85231c7d0e755a --cri-socket unix:///var/run/cri-dockerd.sock

至此,则加入集群成功:

7. 重新加入集群

如果需要重新执行加入集群,则执行:

kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock

再获取TOKEN、discovery-token-ca-cert-hash 参数后,最后执行:

kubeadm join 192.168.3.61:6443 --token dz3s8l.8co7h567py8kbr1n --discovery-token-ca-cert-hash sha256:a7f52953d123a1c7fc6ccdb0ee6c0f0b0c52dbb06ea8592d3f85231c7d0e755a --cri-socket unix:///var/run/cri-dockerd.sock

1. 设置系统主机名及hosts文件

  1. 编辑/etc/hosts文件,添加IP与主机名的映射。若有多个Node,则全部添加。

  1. 执行如下命令设置主机名。
hostnamectl set-hostname k8s-master

2. 更新系统&设置存储库

yum update -y
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

3. 相关设置

3.1. 禁用iptablesfirewalld服务

systemctl stop firewalld
systemctl disable firewalld

systemctl stop iptables
systemctl disable iptables

3.2. 禁用SELinux

sed -i 's/enforcing/disabled/' /etc/selinux/config

3.3. 禁用swap分区

永久关闭swap分区,编辑/etc/fstab文件,将swap行的内容注释掉。

# /dev/mapper/xxx    swap   xxx

3.4. 调整内核参数

/etc/sysctl.d/k8s.conf文件中追加如下三行内容:

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

依次执行如下命令:

sysctl -p
modprobe br_netfilter
lsmod | grep br_netfilter

至此,重启一次操作系统。

4. 安装docker和cri-dockerd(所有节点执行)

4.1. 安装docker

  1. 移除旧版docker。
yum remove docker \
        docker-client \
        docker-client-latest \
        docker-common \
        docker-latest \
        docker-latest-logrotate \
        docker-logrotate \
        docker-engine
  1. 安装docker及其依赖库。
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 启动Docker,设置开机自启动。
# 启动docker
systemctl start docker
# 设置docker开机启动
systemctl enable docker
# 验证
systemctl status docker

4.2. 安装cri-dockerd

K8S 1.24版本后需要使用cri-dockerd和docker通信。

  1. 下载cri-dockerd。
# 若没有wget,则执行
yum install -y wget
# 下载
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd-0.3.4-3.el7.x86_64.rpm
# 安装
rpm -ivh cri-dockerd-0.3.4-3.el7.x86_64.rpm
# 重载系统守护进程
systemctl daemon-reload
  1. 设置镜像加速。

Docker Hub 是 Docker 官方提供的一个公开的 Registry,里面存储了很多常用的镜像,当我们使用 Docker 运行容器时,如果本地没有这个镜像,它就会到 Docker Hub 去下载。但是,由于 Docker Hub 服务器在国外,所以在国内下载速度比较慢。而 Registry Mirror 也被称为 Docker 镜像加速器,它实际上就是一个代理服务器,能够提供更快的镜像下载速度。

为了从国内的镜像托管站点获得镜像加速支持,建议修改Docker的配置文件,增加Registry Mirror参数,将镜像配置写入配置参数中。

编辑/etc/docker/daemon.json,设置:

{
  "registry-mirrors": ["https://c12xt3od.mirror.aliyuncs.com"]
}
  1. 修改配置文件/usr/lib/systemd/system/cri-docker.service,修改第10行ExecStart=为:
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9

其中pause:3.9版本是根据K8S的版本相关,当前安装v1.28.2版本的K8S时,通过如下命令得知pause的版本为3.9:

kubeadm config images list --kubernetes-version v1.28.2

  1. 自启动、重启Docker组件。
# 重载系统守护进程
systemctl daemon-reload
# 设置cri-dockerd自启动
systemctl enable cri-docker.socket cri-docker
# 启动cri-dockerd
systemctl start cri-docker.socket cri-docker
# 检查Docker组件状态
systemctl status docker cir-docker.socket cri-docker

5. 安装Kubernetes

5.1. 配置repo源

/etc/yum.repos.d/目录下创建kubernetes.repo文件,内容如下:

[kubernetes]
name=Kubernetes Repository
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

5.2. 安装kubectl&kubelet&kubeadm(所有节点执行)

名称 说明
kubectl Kubernetes 的命令行工具,人们通常通过它与Kubernetes 进行交互。
kubelet Kubernetes 工作节点上的一个代理组件,运行在每个节点上。
kubeadm 一个提供了 kubeadm init 和 kubeadm join 的工具, 作为创建Kubernetes 集群的“快捷途径” 的最佳实践(用于创建集群)。

执行如下命令安装:

yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

5.3. 检查runc

执行:

runc -v

5.4. 初始化Master节点

执行:

kubeadm init  --node-name=k8s-master --image-repository=registry.aliyuncs.com/google_containers --cri-socket=unix:///var/run/cri-dockerd.sock --apiserver-advertise-address=192.168.3.61 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12

其中--apiserver-advertise-address的值需要修改为实际主机的IP地址。

安装成功后:

因为是root用户安装的,因此将如下环境变量添加到~/.bash_profile中:

export KUBECONFIG=/etc/kubernetes/admin.conf

执行:

source ~/.bash_profile

至此,则K8S Master安装完成。