作者: 李镇伟

timescaleDB双机热备流复制与测试

背景

最近有项目要用到热备功能,timescaledb只能兼容pg的流复制,不能兼容其他的复制策略,所以这里我们采用pg的流复制功能镜像部署,并进行了一些测试


timescaleDB安装(两台机器都安装)

1.添加postgresql源

echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update

2.安装timescaledb

sudo add-apt-repository ppa:timescale/timescaledb-ppa
sudo apt-get update
sudo apt install timescaledb-1.7.5-postgresql-11

3.安装postgis

sudo apt install postgresql-11-postgis-2.5

4.进行数据库调优

sudo timescaledb-tune -yes

5.创建一个300M的占位文件,避免数据库占满硬盘空间,系统无法调试

dd if=/dev/zero of=./useless-placeholder bs=1M count=300

timescaledb流复制配置(主节点配置)

修改配置文件sudo nano /etc/postgresql/11/main/postgresql.conf

 
# postgresql.conf
wal_level = replica
max_wal_senders = 16                      # 最多多少各流复制链接
wal_keep_segments = 256                   # 流复制保留最多的xlog数
wal_sender_timeout = 60s                  # 流复制主机发送数据超时时间
max_connections = 1000                    # 从库的max_connections必须大于主库的
 
full_page_writes = on                     # 使用pg_rewind命令同步数据库要用
wal_log_hints = on                        # 使用pg_rewind命令同步数据库要用
hot_standby = on                          # 使用pg_rewind命令同步数据库要用
 
listen_addresses = '*'                    # 修改监听
archive_mode = on                         # 开启归档模式
archive_command = 'arch.sh %f %p'

创建replica用户,密码replica123

sudo -u postgres psql
CREATE ROLE replica login replication encrypted password 'replica123';

在/var/lib/postgresql/11/main创建arch.sh,用于定时删除超过7天的归档文件内容如下


PGDATA=/var/lib/postgresql/11/main
#test ! -f $PGDATA/arch/$1 && cp -r --preserve=timestamps $2 $PGDATA/arch/$1 ; find $PGDATA/arch/ -type f -mtime +1 -exec rm -f {} \;
test ! -f $PGDATA/arch/$1 && cp -r --preserve=timestamps $2 $PGDATA/arch/$1 ;
# 一天的日志量太大,还是删除最近20个的吧
num=`ls -l $PGDATA/arch | grep '^-' | wc -l`
cd $PGDATA/arch
if [ $num -gt 20 ];
then
 #计算超过5个多少
 num=`expr $num - 20`
 clean=`ls -tr | head -$num | xargs`
 echo "will delete file:"
 echo ${clean}
 #-n1 每次处理1个文件
 ls -tr | head -$num | xargs -i -n1 rm -rf {}
fi

在/var/lib/postgresql/11/main创建arch目录,赋权给arch和arch.sh

mkdir /var/lib/postgresql/11/main/arch
chown -R postgres:postgres arch*

确认归档功能开启

root@database-master:/var/lib/postgresql/11/main# ps -ef|grep archiver
postgres 29921 29916  0 08:36 ?        00:00:00 postgres: 11/main: archiver  
root     29953 29477  0 08:36 pts/0    00:00:00 grep --color=auto archiver

配置sudo nano /etc/postgresql/11/main/pg_hba.conf

备注:192.168.0.31 是备节点的IP

# 在配置文件末尾添加
pg_hba.conf
host    all             all             0.0.0.0/0               md5
host    replication     replica         192.168.0.31/32         md5

重启数据库

sudo systemctl restart postgresql

timescaledb流复制配置(从节点配置)

配置sudo nano /etc/postgresql/11/main/pg_hba.conf

# 在配置文件末尾添加
pg_hba.conf
host    all             all             0.0.0.0/0               md5
host    replication     replica         192.168.0.31/32         md5

删除数据目录

sudo rm -rf /var/lib/postgresql/11/main
sudo pg_basebackup -D /var/lib/postgresql/11/main -Fp -Xs -v -P -h 192.168.0.30 -U replica -W

复制之后,注意设置main目录的权限为postgres


sudo chown -R postgres:postgres /var/lib/postgresql/11/main
sudo systemctl restart postgresql

在 /var/lib/postgresql/11/main 下添加recovery.conf文件,内容如下:

注意192.168.0.30是主节点的IP

standby_mode = on
primary_conninfo = 'host=192.168.0.30 port=5432 user=replica password=replica123'
recovery_target_timeline = 'latest'

修改配置文件sudo nano /etc/postgresql/11/main/postgresql.conf

# postgresql.conf
max_connections = 10000                    # 从库的max_connections必须大于主库的
max_standby_streaming_delay = 30s
wal_receiver_status_interval = 10s
hot_standby_feedback = on

full_page_writes = on                     # 使用pg_rewind命令同步数据库要用
wal_log_hints = on                        # 使用pg_rewind命令同步数据库要用
hot_standby = on                          # 使用pg_rewind命令同步数据库要用

listen_addresses = '*'

重启数据库

sudo systemctl restart postgresql

场景测试

功能说明:

主库可读可写,备库只可读。备库的数据会通过异步的方式实时从主库同步。

备库关闭,不影响主库的使用,备库重启之后,能自动从主库同步这段时间缺失的数据。

主库关闭,备库不会自动切换成主库,等主库开机之后,主备功能自动恢复。

场景1:确认foreign table可兼容双击热备

步骤1:在master机器上创建两个库,并对其中的一些表之间建立起foreign table。

步骤2:检查slver机器上也自动生成了两个库和对应的外表

步骤3:在测试环境上安装应用程序,进行sql insert操作

步骤4:检查master和slaver上的4张表数据是否一致

结论:foreign table功能能兼容双击热备,不会丢数据

场景2:在小数据量时,如果备库关闭,过一段时间再重启,会有什么后果?

步骤1:在完成场景1的情况下,修改插入频率,提高到每间隔1秒500条数据

步骤2:持续了2分钟之后,突然在slaver机器上运行systemctl stop postgresql

步骤3:master机器继续工作,master上的数据持续增加

步骤4:1小时后,在slaver机器上运行systemctl start postgresql 启动数据库

步骤5:检查slaver机器上缺少的数据是否会补充回来

结论:slaver机器关闭再重启,这段时间缺失的数据会补充回来

场景3:在大数据量时,如果备库关闭,过一段时间再重启,会有什么后果?

步骤1:在完成场景1的情况下,修改插入频率,提高到每间隔1秒500000个条数据

步骤2:持续了2分钟之后,突然在slaver机器上运行systemctl stop postgresql

步骤3:master机器继续工作,master上的数据持续增加

步骤4:1小时候在slaver机器上运行systemctl start postgresql 启动数据库

步骤5:检查slaver机器上缺少的数据是否会补充回来

结论:slaver机器关闭再重启,这段时间缺失的数据会通过wal日志补充回来,补充速度看备机的硬盘io

场景4:在大数据量时,如果主库关闭,过一段时间再重启,主备能自动恢复连接吗?

步骤1:在完成场景1的情况下,修改遥测频率,提高到每间隔30秒50000个遥测数据

步骤2:持续了一段时间之后,突然在master机器上运行systemctl stop postgresql

步骤3:此时应用程序出错,遥测无法上传

步骤4:过60分钟之后,在master机器上运行systemctl start postgresql 启动数据库

步骤5:检查连接,和主备数据库,删除和增加数据,检查是否自动同步

select client_addr,sync_state from pg_stat_replication;

结论:master机器关闭再重启,能够自动与备库建立连接,并且不影响后续使用,但是这里要注意了,如果关闭时间过长,会产生巨量的pg_wal日志,速度很快,一天可能100G+此时不能删除pg_wal日志,还是需要把备库完全起来,等备库完成了数据同步之后,通过

pg_controldata /var/lib/postgresql/11/main命令找到【Latest checkpoint location】,然后通过pg_archivecleanup -d /var/lib/postgresql/11/main/pg_wal 【Latest checkpoint location】来清理日志文件,若备库没有起来,千万不要提前删除,会导致备库数据不同步,只能通过pg_rewind重做备库。在没有出问题的情况下。pg_wal的日志会根据max_wal_size配置进行自动清理

场景5:主库关闭,备库切换成主库,原主库能改成备库吗,程序能继续使用吗?

步骤1:关闭主库systemctl stop postgresql

步骤2:在备库上linux用户切换到postgres,然后添加pg_ctl到环境变量

$ cd ~
$ vim .profile
PATH=$PATH:/usr/lib/postgresql/11/bin
export PATH
$ . ~/.profile

步骤3:在备库上输入pg_ctl promote -D /var/lib/postgresql/11/main。此时会发现/var/lib/postgresql/11/main下的recovery.conf变成了recovery.done

postgres@database-slaver:/home/sfere$ pg_ctl promote -D /var/lib/postgresql/11/main
waiting for server to promote.... done
server promoted

步骤4:在老的主库上,使用postgres用户登录,使用pg_rewind同步数据

pg_rewind -D /var/lib/postgresql/11/main --source-server='hostaddr=192.168.0.31 port=5432 user=postgres password=postgres'

步骤5:修改应用程序的数据库连接配置到新的主库,继续进行sql insert操作

结论:主库备库切换完成之后,修改应用程序数据库连接池配置,不影响后续使用

argoCD与droneCI结合

背景

我们的CI/CD流程采用了argoCD与droneCI两款工具,droneCI的关键文件是drone.yaml文件,配置在开发代码里。 argoCD的关键是helm包和不同环境的values.yaml参数。两者需要打通起来,让开发人员专注提交业务代码,后续程序的自动更新,部署等问题不影响他们。

流程图

droneCI需要修改的部分

---
kind: pipeline
type: kubernetes
name: argocd
steps:
  - name: argocd deploy
    image: drone-argocd-plugin(自己制作的,就是一个ubuntu基础镜像,里面安装了一个argocd-cli工具)
    environment:
      ARGOCD_AUTH_TOKEN:
        from_secret: argocd_auth_token
     
      ARGOCD_SERVER:
        from_secret: argocd_server
    commands:
      - argocd --insecure app set 应用程序名 -p 应用镜像tag号=git-${DRONE_COMMIT_SHA:0:10}
      - argocd --insecure app sync 应用程序名
depends_on:
  - push
trigger:
  branch:
    - develop
  event:
    - push
---
kind: secret
name: argocd_server
get:
  path: drone/data/argocd
  name: server
---
kind: secret
name: argocd_auth_token
get:
  path: drone/data/argocd
  name: auth_token
这块代码的主要作用就是,在drone推送镜像到私有仓库之后,通过argocd的cli工具,加载argocd的登录信息,对argocd上,需要更新的应用程序设置镜像tag号,然后触发更新操作,完成自动更新

argoCD需要准备的内容

1.准备一个git仓库如下图。helm目录下放置需要部署的应用程序的所有helm文件夹,node目录放置每个节点集群需要的values.yaml文件,如开发环境是dev.yaml,测试环境是test.yaml,生产环境是prod.yaml

2.在argoCD上部署应用app,如下图所示,只要设置好对应的git仓库,helm路径,values路径即可

(此处也是笔者踏了很多坑得出的结论,最好使用git和submodule的方式来管理,不要使用harbor仓库等方式管理helm和values,因为argocd有一些设置是不符合使用习惯的,除非这个pr被合并https://github.com/argoproj/argo-cd/pull/6280)

全部打通完成之后,开发人员只要正常提交代码,通过sonarqube等扫描工具之后,代码合入develop分支之后,会触发argoCD根据git-hash自动更新,更新完成会在gitea的代码仓库上打一个小绿标,全程无人值守,666

自定义一个kaniko镜像

背景

kaniko是一款方便我们从K8S内部构建docker容器的工具,以前我们在CI过程中,使用的是docker-in-docker技术,这种技术最主要的缺陷就是当一台机器上同时运行多个docker build流水线时,会出现阻塞的情况,因为这一批流水线用的是宿主机上的同一个docker进程。
基于这种情况,我们在droneCI流水线中换用了kaniko来进行docker镜像的创建。

遇到的难题

  1. kaniko是基于scratch构建的,里面没有shell,所以想在kaniko原生镜像里在调用python是很麻烦的
  2. kaniko创建docker镜像使用的是file system功能,如果想在一个kaniko容器里先创建ubuntu镜像,再创建alpine镜像, 是会有各种冲突问题的,需要使用–cleanup功能。此功能会清空文件系统,同时如果有自己装的shell,也会被清空,导致无法再次使用

解决方案

  1. kaniko的关键文件其实是/kaniko目录下的哪些 二进制文件,官方推荐是用gcr.io/kaniko-project/executor 镜像,其实我们可以拷贝这个/kaniko目录到我们自己的私有镜像
  2. shell没有的话,我们可以拷贝一个busybox进去,这样就有shell了
  3. 虽然–cleanup会清空file system,但是根据代码里的ignorepath设定,volume挂载目录和/kaniko目录会被忽略掉。所以我们可以有两种方式选择:一、通过volume的方式哦挂载busybox和自己的python代码到私有镜像里。二、把busybox和python代码加入/kaniko目录。

示例代码

Dockerfile如下:

FROM heiheidoc/kaniko-project-executor:v1.3.0 AS plugin

# 1.6.0的clean up有问题 https://github.com/GoogleContainerTools/kaniko/issues/1586

FROM heiheidoc/kaniko-project-executor:debug AS debug

FROM python:3.9.5-buster

COPY --from=背景plugin /kaniko /kaniko

COPY --from=debug /busybox /kaniko/busybox

ADD . /kaniko

ENV DOCKER_CONFIG /kaniko/.docker

CMD ["python3","/kaniko/main.py"]


部分python代码如下,功能是按照一定规则生成Docker镜像:

def run_shell(shell):
    print_green(shell)
    cmd = subprocess.Popen(shell, stdin=subprocess.PIPE, stderr=sys.stderr, close_fds=True,
                           stdout=sys.stdout, universal_newlines=True, shell=True,executable='/kaniko/busybox/sh', bufsize=1)
    cmd.communicate()
    return cmd.returncode
def run_executor():
    for folder_name, sub_dir, files in os.walk(os.getcwd()):
        if 'Dockerfile' in files:
            Dockefile_path = folder_name + "/Dockerfile"
            docker_info = folder_name.replace(os.getcwd(),'').split('/')
            harbor_image_name = REGISTRY_URL + "/" + owner_name + "/" + docker_info[1] + ":" + docker_info[2]
            cmd_build = "/kaniko/executor --cache=true --cache-dir=/cache --cleanup --skip-tls-verify --skip-tls-verify-pull --skip-tls-verify-registry" \
                        " --dockerfile=" + Dockefile_path + \
                        " --context=dir://" + folder_name + \
                        " --destination=" + harbor_image_name
            assert run_shell(cmd_build) == 0, "镜像build失败: " + harbor_image_name
if __name__ == "__main__":
    run_executor()

K3S环境下接入Prometheus,grafana,等监控套件

背景

因为常规的监控都是用K8S做的,而K3S上的监控方案少之又少,如果直接用rancher上的prometheus监控,会消耗至少2G的内存,于是我们就自己做了K3S和pg数据库的监控,并且通过我们自己做的监控,可以减少一些不必要的性能开销。主要监控容器资源消耗,宿主机资源消耗,pg数据库资源消耗

这个是资源使用情况,大约会用掉600M内存和100MCPU

user@user:/$ kubectl top pod -n kube-ops
NAME CPU(cores) MEMORY(bytes)
grafana-0 1m 47Mi
kube-state-metrics-594fb7bc84-5mg6g 3m 10Mi
node-exportor-prometheus-node-exporter-sznls 31m 8Mi
node-exportor-prometheus-node-exporter-tx7rm 13m 7Mi
prometheus-0 46m 565Mi
prometheus-postgres-exporter-6c858f47d4-dj9hj 13m 6Mi

prometheus监控组件参考helm chart

https://github.com/prometheus-community/helm-charts/tree/main/charts
我魔改的github连接
https://github.com/lizhenwei/k3s-prometheus


Prometheus的安装

1.创建一个命名空间kube-ops,把监控用的东西都放在这个命名里面。
2.使用我魔改的chart进行安装,默认版本是v2.26.0,默认启用上图提到的

cadvisor,kube_state_metrics,node_exportor,postgres_exporter

 

kubectl create ns kube-ops
helm install -n kube-ops prometheus lizhenwei-prometheus

如果要关闭其中的某个监控项,安装时参考添加变量 –set node_exportor.enable=false,
prometheus的数据会用默认的storageClass生成PVC,如果没有默认的,参考手动设置nfs存储 –set persistence.storageClass=nfs-client
安装成功后,因为我是nodeport暴露出来的,所以可以通过浏览器去检查一下配置,例如这里我们暴露出来是32331端口可以访问,例如:

$ kubectl get svc -n kube-ops
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus NodePort 10.43.178.128 <none> 9090:32331/TCP 2d4h

访问http://master机器IP:32331/targets,可以看到prometheus自己已经是成功起来了,我们也可以去http://master机器IP:32331/config页面看看配置项是否都正确
要启用或停用某些监控功能,可以修改lizhenwei-prometheus/valuse.yaml里的配置,修改成true或false


kube-state-metrics的安装

kube-state-metrics是用来收集k8s集群的CPU,内存等信息的收集器,这里我用的是v1.9.7版本。
使用我github上的helm进行安装:

helm install -n kube-ops prometheus lizhenwei-kube-state-metrics

要想验证部署kube-state-metrics之后,是否能成功使用,我们可以看prometheus的target页面是不是显示kube-state-metrics(X/X up) x为机器节点数量。
然后我们去graph页面看看,http://master机器IP:32331/graph。可以参考官网给的promql文档,输入几个语句试试

PromQL参考链接

https://github.com/kubernetes/kube-state-metrics/tree/master/docs

例如输入kube_configmap_info,点击execute会返回一些结果,如下图


K3S自带的CADVISOR

K3S自带kubelet ,而cadvisor已经集成在kubelet里了,prometheus可以通过配置找到本地安装的cadvisor,例如下列代码:

- job_name: 'cadvisor'
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - action: labelmap
    regex: __meta_kubernetes_node_label_(.+)
  - target_label: __address__
    replacement: kubernetes.default.svc:443
  - source_labels: [__meta_kubernetes_node_name]
    regex: (.+)
    target_label: __metrics_path__
    replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

接入prometheus的时候,可以根据以下链接,查看PromQL语句

PromQL参考链接

https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md


node-exportor的安装

这个使用官方网站给的一个公共库就可以了

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install node-exportor prometheus-community/prometheus-node-exporter

grafana参考链接https://grafana.com/grafana/dashboards/1860


postgres-exportor

下载代码https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-postgres-exporter 到机器上
修改valuse.yaml里的queries里的参数,在最后面加上

pg_stat_activity:
      query: |
        SELECT
          datname,
          SUM(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change))::bigint)::float AS process_idle_seconds_sum,
          COUNT(*) AS process_idle_seconds_count
        FROM pg_stat_activity
        WHERE state = 'idle'
        GROUP BY datname
      metrics:
        - datname:
            usage: "LABEL"
            description: "datname"
        - process_idle_seconds:
            usage: "COUNTER"
            description: "Idle time of server processes"
        - process_idle_seconds_sum:
            usage: "GUAGE"
            description: "sum of Idle time of server processes"

在valuse.yaml文件的config.datasource部分添加我们的postgres超管用户信息。

helm安装语句

helm install -n kube-ops prometheus-postgres-exporter prometheus-postgres-exporter

Grafana导入dashboard

可以参考这位大神的github链接https://github.com/starsliao/Prometheus


页面截图

 

rancher备份K8S集群数据到minio方案

1 安装minio

使用自定义证书,并且提供https
docker安装,数据和配置挂载到宿主机上

1.1 证书生成命令

# 制作两个目录用于存放minio数据
mkdir -p /home/lizhenwei/minio/data
mkdir -p /home/lizhenwei/minio/config/certs
# 进入minio证书目录
cd  /home/sfere/lizhenwei/config/certs
# 使用openssl产生伪随机字节
openssl rand -writerand .rnd
# 创建私钥
openssl genrsa -out private.key 2048
# 创建证书文件
openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=CN/ST=NanJing/L=YuHua/O=LZW/CN=192.168.0.237"

完成之后,/home/lizhenwei/minio/config/certs目录下应该会有CAs  private.key  public.crt 三个文件或目录,其中public.crt 是我们后面要填入rancher中的证书文件

1.2 docker运行minio

docker run -d -p 443:443 --name minio-rancher   -e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE"   -e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"   -v /home/lizhenwei/minio/data:/data   -v /home/lizhenwei/minio/config:/root/.minio   minio/minio server --address ":443" /data

2 rancher中配置集群数据备份到minio

2.1.登录minio,创建bucket

2.2 在rancher中设置etcd备份到S3存储(minio)

Docker安装redis环形集群

背景

因为有需求要3台机器来做一个redis高可用(o(╥﹏╥)哭o~~~),没办法,只能用一个奇怪的方式安装redis集群了。这里我们用的不是主从哨兵哦,阅读本文的作者不要误会啦。再就是,真不推荐用3个机器来做redis集群。

因为配置里的cluster-announce-ip不能用域名,只能用ip,而pod的IP在K8S里经常变,所以不能用K8S部署了,我们这里使用docker和docker-compose部署,总得来说还是很简单的,代码我上传至github上了
https://github.com/lizhenwei/redis-cluster-in-docker.git

拓扑图

假设我们用3台机器,IP地址192.168.0.94,192.168.0.95,192.168.0.96 ;分别是node1,node2,node3

-------    -------    -------
|node1| ---|node2|----|node3|
-------    -------    -------
master1    master2    master3
slaver2    slaver3    slaver1

安装完毕之后,需要我们手动通过`CLUSTER REPLICATE`命令调节master和slaver所处的容器,形成如上拓扑,这样假使node1挂掉的时候,我们的node2上能运行一个master2,node3上运行master3,master1(此处的master1是由slaver1变过来的)

安装方法

1.在每台机器上安装docker和docker-compose。国内可以用daocloud去下载。会比较快http://get.daocloud.io/
2. 在每台机器上下载该代码,进入代码目录,运行shell命令,会根据IP地址更改配置文件,并且创建redis的docker应用:

# 在每台机器上输入该命令,注意替换IP地址
bash docker-init.sh 192.168.0.94
3. 在任意一台机器上通过redis-cli创建集群
# 在每台机器上输入该命令,注意替换IP地址
bash redis-init.sh 192.168.0.94 192.168.0.95 192.168.0.96
# 弹出来的提示直接输入yes
4. 完成之后执行命令,检查集群是否运行成功
#进入redis容器
docker exec -it redis-cluster bash
#检查集群是否运行成功
redis-cli -a 92F1q99f9CnrkAuwJPItdj8brqeMtN3r -p 7000 cluster nodes

python代码访问redis-cluster

$ pip install redis-py-cluster
```
测试代码
```
>>> from rediscluster import RedisCluster
>>> # Requires at least one node for cluster discovery. Multiple nodes is recommended.
>>> startup_nodes = [{"host": "192.168.0.94", "port": "7000"}, {"host": "192.168.0.94", "port": "7001"},{"host": "192.168.0.95", "port": "7000"}, {"host": "192.168.0.95", "port": "7001"},{"host": "192.168.0.96", "port": "7000"}, {"host": "192.168.0.96", "port": "7001"}]
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True,password='password')
>>> rc.set("foo", "bar")
True
>>> print(rc.get("foo"))
'bar'

Docker运行ApacheIoTDB

ApacheIoTDB-Server的部署方式

ApacheIoTDB提供了三种部署方式:源码部署,二进制程序部署,Docker部署
因为我的电脑是Ubuntu的,不兼容ApacheIoTDB,所以我采用了docker方式进行部署(docker是用debian的java镜像)


部署服务端

1.在ubuntu机器上创建目录~/iotdb-0.11.2
2.复制官方网站的dockerfile到本地:https://github.com/apache/iotdb/blob/master/docker/src/main/Dockerfile-0.11.2
3.输入以下命令制作镜像,确认docker 镜像生成成功

docker build -t iotdb:0.11.2 .

4.输入以下命令,运行iotdb,并且把数据目录和日志目录挂载到~/iotdb-0.11.2下

docker run --name iotdb -p 6667:6667 -v /home/boring/iotdb-0.11.2/data:/iotdb/data -v /home/boring/iotdb-0.11.2/logs:/iotdb/logs -d iotdb:0.11.2 /iotdb/bin/start-server.sh

在容器中用命令行工具进行测试

1.进入容器

docker exec -it iotdb bash

2.使用命令行工具连接

/iotdb/sbin/start-cli.sh -h 127.0.0.1 -p 6667 -u root -pw root

3.确认界面出现如下返回

---------------------
Starting IoTDB Cli
---------------------
 _____       _________  ______   ______
|_   _|     |  _   _  ||_   _ `.|_   _ \
  | |   .--.|_/ | | \_|  | | `. \ | |_) |
  | | / .'`\ \  | |      | |  | | |  __'.
 _| |_| \__. | _| |_    _| |_.' /_| |__) |
|_____|'.__.' |_____|  |______.'|_______/  version 0.11.2
IoTDB> login successfully
IoTDB>

DataStreams+logstash+ILM进行日志定时删除,节省硬盘资源

背景

目前所有的K8S上的容器日志都被收集到了我们的ELK上,随着时间的推移,ELK上的日志所占的存储空间越来越多,我们需要一个定时清理的策略,以节约硬盘资源。
我们主要配置以下ELK里的这几个地方

  • 通过kibana新增一个lifecycle policies
  • 通过kibana新增一个index template,注意配置DataStreams
  • logstash 的logstashPipeline
  • filebeat的filebeat.yml文件

简要配置图


Kibana上添加 Lifecycle Policies

1.点击菜单栏的【management】->点击【stack management】
2.点击DATA目录下的【Index Lifecycle Policies】
3.点击【Create policy】创建一个新的生命周期规则
4.测试的话,规则就随便配置一个每10分钟迭代一个新的,删除超过1小时的index
期望效果:
对应的index会从00001开始每隔10分钟往上+1,同时最多存在7个index。


Kibana上添加Index Templates

1.点击菜单栏的【management】->点击【stack management】
2.点击DATA目录下的【Index Management】
3.点击【Index Templates】小标签,【Create template】创建模板
4.index patterns匹配我们logstash上传来的index,比如192*
5.Data stream的配置按钮打开

6.index settings配置上我们上一步添加的Lifecycle Policies

7.mappings参数需要配置【mapped fields】和【Dynamic Template】内容可以从logstash的配置里完整复制过来
8.其他的诸如component telmpalte 和Aliases都不用配置了。保存这个index template就行了


logstash配置

因为要动态生成index,所以要写一些filter规则,这里就不贴出来了。关键注意output里要设置

"action" => "create"和ilm_enabled => false
logstash.conf: |
    input {
      beats {
        port => 5044
      }
      tcp {
        port => 9999
      }
      udp {
        port => 9998
      }
    }
    filter {
      json {
        source => "message"
      }
      if [app_name] {
        mutate {
          add_field => {
            "index_name" => "%{app_name}"
          }
        }
      } else {
        mutate {
          add_field => {
            "index_name" =>  "non_index_log"
          }
        }
      }
    }
    output {
        elasticsearch {
           hosts => ["http://elasticsearch-master-headless:9200"]
           index => "%{index_name}"
           action => "create"
           ilm_enabled => false
        }
        stdout { codec => rubydebug }
    }

filebeat配置

因为有一些日志是通过filebeat传上来的,所以filebeat也要进行少量的配置,传一个app_name到logstash用于生成index

filebeat.inputs:
  - type: log
    paths:
      - "/log/*.log"
processors:
  - decode_json_fields:
        fields: ["message"]
        process_array: false
        max_depth: 1
        target: ""
        overwrite_keys: false
  - add_fields:
      target: ''
      fields:
        app_name: "{{ .Values.nodeSelector.internet_ip}}-aimp-frontend-v2-ux"
output.logstash:
  hosts: ["{{ .Values.logs.logstash.host }}:{{ .Values.logs.logstash.beatport }}"]

Sanic中添加基于Cron表达式的协程定时任务

需求

从页面上触发某一个接口之后,要在sanic里面添加一个计划任务。
例如:从页面上填写一个con表达式,后台根据此cron表达式定时执行任务

'*/1 * * * *'   # 这个是每1分钟执行一次的表达式

需要用到的python包有:Sanic,Apscheduler


示例代码

import time
from sanic import Sanic
from sanic.response import json
app = Sanic("App Name")
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
def cron_job():
    print('打印当前时间:', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
@app.route('/')
async def index(request):
    # generate a URL for the endpoint `post_handler`
    print("浏览器里打开一下首页")
    scheduler = AsyncIOScheduler()
    scheduler.add_job(cron_job, CronTrigger.from_crontab('*/1 * * * *'))
    scheduler.start()
    return json({"hello": "thank you"})
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

实验效果

解决helm部署报错Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress

在使用helm install 或者helm upgrade的时候,如果出现了异常中断操作, 可能会导致如下报错

Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress

那么问题来了,如何解决这个问题呢?
参考github上的issues:https://github.com/helm/helm/issues/8987,我们可以使用以下操作
1.输入helm history 命令检查当前状态, 如下

$ helm history -n lizhewnei lizhewnei-common
REVISION	UPDATED                 	STATUS         	CHART                 	APP VERSION	DESCRIPTION
331     	Tue Feb 23 23:11:07 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
332     	Wed Feb 24 08:11:08 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
333     	Wed Feb 24 15:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
334     	Wed Feb 24 23:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
335     	Thu Feb 25 08:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
336     	Thu Feb 25 15:11:08 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
337     	Thu Feb 25 23:11:06 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
338     	Fri Feb 26 08:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
339     	Fri Feb 26 09:49:37 2021	deployed       	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
340     	Fri Feb 26 10:37:53 2021	pending-upgrade	lizhewnei-common-0.1.0	1.16.0     	Preparing upgrade

2.根据上述状态,我们会发现,最近的一次340部署结果是pending-upgrade 所以阻塞了我们的继续部署
3.我们使用helm rollback命令回退一个版本到339版本

$ helm rollback -n lizhewnei lizhewnei-common 339
Rollback was a success! Happy Helming!

4.回退之后,再检查一次当前状态,确认状态信息是回退到339版本

$ helm history -n lizhewnei lizhewnei-common
REVISION	UPDATED                 	STATUS         	CHART                 	APP VERSION	DESCRIPTION
332     	Wed Feb 24 08:11:08 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
333     	Wed Feb 24 15:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
334     	Wed Feb 24 23:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
335     	Thu Feb 25 08:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
336     	Thu Feb 25 15:11:08 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
337     	Thu Feb 25 23:11:06 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
338     	Fri Feb 26 08:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
339     	Fri Feb 26 09:49:37 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
340     	Fri Feb 26 10:37:53 2021	pending-upgrade	lizhewnei-common-0.1.0	1.16.0     	Preparing upgrade
341     	Fri Feb 26 11:00:23 2021	deployed       	lizhewnei-common-0.1.0	1.16.0     	Rollback to 339

5.这个时候,我们再去使用helm upgrade命令,就可以正常的升级了,升级之后,我们通过helm history 也可以检查到升级成功,

$ helm history -n lizhewnei lizhewnei-common
REVISION	UPDATED                 	STATUS         	CHART                 	APP VERSION	DESCRIPTION
333     	Wed Feb 24 15:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
334     	Wed Feb 24 23:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
335     	Thu Feb 25 08:11:09 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
336     	Thu Feb 25 15:11:08 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
337     	Thu Feb 25 23:11:06 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
338     	Fri Feb 26 08:11:13 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
339     	Fri Feb 26 09:49:37 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
340     	Fri Feb 26 10:37:53 2021	pending-upgrade	lizhewnei-common-0.1.0	1.16.0     	Preparing upgrade
341     	Fri Feb 26 11:00:23 2021	superseded     	lizhewnei-common-0.1.0	1.16.0     	Rollback to 339
342     	Fri Feb 26 11:01:27 2021	deployed       	lizhewnei-common-0.1.0	1.16.0     	Upgrade complete
 
 
 

苏ICP备18047533号-1