月度归档: 2021年9月

用python实现helm template功能

背景

众所周知,helm template 包名 -f values.yaml >输出文件。这个方式能渲染go-template,自动填充{{ .Values.XXX }}参数到文件里。现在有一个需求,需要用python来实现类似的功能。那么就来看看我的最后实现吧


sapmle.tmpl 待填充文件

{{ .Values.Count }} items are made of {{ .Values.Material }}
{{ .Values.Material }} items are made of {{ .Values.Material }}
{{ .Values.Material }} items are made of {{ .Values.Count }}
{{ .Values.mqtt.server }} dadasdjsaijaid

values.yml 参数文件

Count: 14
Material: Wool
mqtt:
  server: 172.15.62.2

python 代码

import re

from ruamel import yaml


def traverse(dic, path=None):
    if not path:
        path = []
    if isinstance(dic, dict):
        for x in dic.keys():
            local_path = path[:]
            local_path.append(x)
            for b in traverse(dic[x], local_path):
                yield b
    else:
        yield path, dic


def template_render(source_file, values_file, dest_file):
    with open(source_file, 'r') as source:
        origin = source.read()

    with open(values_file, 'r', encoding='utf-8') as vaules:
        result = yaml.load_all(vaules.read(), Loader=yaml.Loader)
        yaml_dict = list(result)[0]
    for x in traverse(yaml_dict):
        match = "\{\{ \.Values." + '.'.join(x[0]) + " \}?\}"
        origin = re.sub(match, str(x[1]), origin)

    with open(dest_file, 'w+') as dest:
        dest.write(origin)


if __name__ == '__main__':
    template_render('sample.tmpl', "values.yml","result.yaml")

result.yaml 渲染结果

14 items are made of Wool
Wool items are made of Wool
Wool items are made of 14
172.15.62.2 dadasdjsaijaid

ECK安装elasticsearch,接入apm测试

任务目标

以前都是用helm安装elasticsearch,最近发现elasticsearch推荐使用ECK在K8S上安装,那我们就来试试吧

我们会在已有的K8S上安装ECK,elasticsearch,kibana,apm,关闭ssl,loadbalancer暴露应用访问

测试golang接入apm

ECK创建过程

1.先安装上operator

kubectl create -f https://download.elastic.co/downloads/eck/1.7.1/crds.yaml
kubectl apply -f https://download.elastic.co/downloads/eck/1.7.1/operator.yaml

2.安装elasticsearch

cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: quickstart
spec:
  version: 7.14.1
  nodeSets:
  - name: default
    count: 1
    config:
      node.store.allow_mmap: false
EOF

3.安装kibana

cat <<EOF | kubectl apply -f -
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: quickstart
spec:
  version: 7.14.1
  count: 1
  elasticsearchRef:
    name: quickstart
EOF

4.安装apm

cat <<EOF | kubectl apply -f -
apiVersion: apm.k8s.elastic.co/v1
kind: ApmServer
metadata:
  name: apm-server-quickstart
  namespace: default
spec:
  version: 7.14.1
  count: 1
  elasticsearchRef:
    name: quickstart
EOF

5.暴露kibana可外部访问,并且关闭ssl

kubectl edit kibanas.kibana.k8s.elastic.co quickstart。这里只贴上关键的spec部分代码

spec:
  count: 1
  elasticsearchRef:
    name: quickstart
  enterpriseSearchRef:
    name: ""
  http:
    service:
      metadata: {}
      spec:
        type: LoadBalancer
    tls:
      selfSignedCertificate:
        disabled: true

6.暴露apm可外部访问

kubectl edit apmserver.apm.k8s.elastic.co/apm-server-quickstart

修改的内容与上面kibana修改内容一致。


7.获取kibana登录用户名和密码

默认用户名 elastic

默认密码使用如下命令获取

kubectl get secret quickstart-es-elastic-user -o go-template='{{.data.elastic | base64decode }}'

8.获取apm-server的secret-token

kubectl get secret/apm-server-quickstart-apm-token -o go-template='{{index .data "secret-token" | base64decode}}'

golang测试APM-SERVER通信

1.设置环境变量,

# 服务名,不设置的话,就是代码的文件名
export ELASTIC_APM_SERVICE_NAME=

# apm服务器地址
export ELASTIC_APM_SERVER_URL=http://localhost:8200

# 我们上一步拿到的token
export ELASTIC_APM_SECRET_TOKEN=

# 可以设置也可以不设置,用于标识环境的,类似标签功能
export ELASTIC_APM_ENVIRONMENT=

2.编写golang测试代码main.go

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"go.elastic.co/apm/module/apmgorilla"
)

func helloHandler(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "Hello, %s!\n", mux.Vars(req)["name"])
}
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/hello/{name}", helloHandler)
	r.Use(apmgorilla.Middleware())
	log.Fatal(http.ListenAndServe(":8000", r))
}

3,在kibana上检查apm的信息,应该会看到一个main的server,有一些数据,如下图所示,证明apm可成功连通

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操作

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


苏ICP备18047533号-2