0%

场景:

  • SSH 跳板机:10.0.0.1
  • MySQL 数据库:10.0.0.2:3306

MySQL 部署的机器不允许 SSH 连接,并且数据库端口只允许 localhost 或 10.0.0.1 这台跳板机访问,此时本机可以通过 ssh 连上跳板机,通过 ssh 建立的隧道端口转发连接上 MySQL 数据库。

阅读全文 »

架构是这样定义的

  • 每个系统都有一个架构
  • 架构由架构元素以及相互之间的关系构成
  • 系统是为了满足 利益相关者(stakeholder) 的需求而构建的
  • 利益相关者都有自己的关注点(concerns)
  • 架构由架构文档描述
  • 架构文档描述了一系列的架构视角
  • 每个视角都解决并且对应到利益相关者的关注点。

架构师的首要任务是尽最大可能找出所有利益相关者,业务方,产品经理,客户/用户,开发经理,工程师,项目经理,测试人员,运维人员,产品运营人员等等都有可能是利益相关者,架构师要充分和利益相关者沟通,深入理解他们的关注点和痛点,并出架构解决这些关注点。架构师常犯错误是漏掉重要的利益相关者,沟通不充分,都会造成架构有欠缺,不能满足利益相关者的需求。利益相关者的关注点是有可能冲突的,比如管理层(可管理性)vs技术方(性能),业务方(多快好省)vs 技术方(可靠稳定),这需要架构师去灵活平衡,如何平衡体现了架构师的水平和价值。

阅读全文 »

Kubernetes 环境安装

面向生产:kubeadmin

环境准备

IP 主机名 用途
192.168.1.1 k8s-master master、etcd
192.168.1.2 k8s-node-1 node1
192.168.1.3 k8s-node-2 node2

准备工作

设置三台机器的主机名

1
2
3
4
5
6
# 在 master 上执行
hostnamectl --static set-hostname k8s-master
# 在 node1 上执行
hostnamectl --static set-hostname k8s-node-1
# 在 node2 上执行
hostnamectl --static set-hostname k8s-node-2

设置 hosts

在三台机器上设置 hosts,均执行如下命令:

1
2
3
4
echo '192.168.1.1    k8s-master
192.168.1.1 etcd
192.168.1.2 k8s-node-1
192.168.1.3 k8s-node-2' >> /etc/hosts

关闭 selinux

1
2
setenforce 0
sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

网络配置

master 机

1
2
3
4
5
6
7
8
9
10
firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10252/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --reload
modprobe br_netfilter
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
sysctl -w net.ipv4.ip_forward=1

node 机

1
2
3
4
5
6
7
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --permanent --add-port=30000-32767/tcp
firewall-cmd --permanent --add-port=6783/tcp
firewall-cmd --reload
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
sysctl -w net.ipv4.ip_forward=1

安装 kubelet kubeadm kubectl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
exclude=kube*
EOF

# 将 SELinux 设置为 permissive 模式(将其禁用)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

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

systemctl enable kubelet && systemctl start kubelet

参考:https://kubernetes.io/zh/docs/setup/independent/install-kubeadm/#%E5%AE%89%E8%A3%85-kubeadm-kubelet-%E5%92%8C-kubectl

安装 etcd 服务

1
yum install -y etcd

更改配置

1
vi /etc/etcd/etcd.conf

创建集群

面向试用:minikube

指引:https://kubernetes.io/docs/tasks/tools/install-kubectl/

安装 VM 驱动

腾讯云 CVM 未能启用驱动启动 minikube,安装驱动的过程可忽略。

- VirtualBox

CentOS:虚拟机不支持内部 VM,未在物理机上尝试

1
2
3
4
5
6
7
8
9
cd /etc/yum.repos.d/
wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
yum update

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install -y binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms
yum install -y VirtualBox-5.2

service vboxdrv start

MAC 上可以直接下载安装:https://www.virtualbox.org/wiki/Downloads

- KVM2

安装成功,但 minikube start 时未能尝试成功

https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm2-driver

1
2
3
4
5
6
yum -y install libvirt-daemon-kvm qemu-kvm

curl -Lo docker-machine-driver-kvm2 https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2 \
&& chmod +x docker-machine-driver-kvm2 \
&& sudo cp docker-machine-driver-kvm2 /usr/local/bin/ \
&& rm docker-machine-driver-kvm2

附:查看虚拟机网络以及使用不同的网络启动 minikube

1
2
3
4
5
yum -y install libvirt virt-install bridge-utils
# 查看虚拟机网络
virsh net-list --all
# 使用不同的虚拟机网络(minikube-net)
minikube start --vm-driver kvm2 --kvm-network minikube-net

- 其他驱动

指引:https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm-driver

安装 kubectl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# CentOS
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 install -y kubectl

# MAC: 方式一
brew install kubernetes-cli
# MAC:方式二
curl -Lo kubectl http://storage.googleapis.com/kubernetes-release/release/v1.5.1/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/

# 安装校验
kubectl version

# 确保服务已启动
systemctl enable kubelet.service
systemctl start kubelet.service

安装 minikube

指引:https://github.com/kubernetes/minikube/releases

1
2
3
4
5
6
7
8
# CentOS
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.29.0/minikube-linux-amd64 \
&& chmod +x minikube \
&& sudo cp minikube /usr/local/bin/ \
&& rm minikube

# MAC
brew cask install minikube

运行

(使用 KVM2 驱动)运行之前

1
2
3
4
5
6
7
8
9
10
11
# 启动服务
systemctl enable libvirtd && systemctl start libvirtd

# 查看进程文件
ls -l /var/run/libvirt/libvirt-sock

# 若进程文件不存在,则修改配置:
vi /etc/libvirt/libvirtd.conf

# 取消行前注释,重新启动服务
#unix_sock_dir = "/var/run/libvirt"

拉取 k8s 相关镜像

原本在 minikube start 命令中会自动拉取镜像,但是因为众所周知的原因,我们无法成功拉取到镜像。这里可以使用阿里 docker 容器镜像服务:https://dev.aliyun.com/search.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 进入虚拟机拉取,而非本机
minikube ssh

# 拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/k8sth/kube-apiserver-amd64:v1.10.0
docker pull registry.cn-hangzhou.aliyuncs.com/k8sth/kube-controller-manager-amd64:v1.10.0
docker pull registry.cn-hangzhou.aliyuncs.com/k8sth/kube-scheduler-amd64:v1.10.0
docker pull registry.cn-hangzhou.aliyuncs.com/k8sth/etcd-amd64:3.1.12
docker pull registry.cn-shenzhen.aliyuncs.com/kubernetes_google/kubernetes-dashboard-amd64:v1.10.0

# 修改 tag
docker tag registry.cn-hangzhou.aliyuncs.com/k8sth/kube-apiserver-amd64:v1.10.0 k8s.gcr.io/kube-apiserver-amd64:v1.10.0
docker tag registry.cn-hangzhou.aliyuncs.com/k8sth/kube-controller-manager-amd64:v1.10.0 k8s.gcr.io/kube-controller-manager-amd64:v1.10.0
docker tag registry.cn-hangzhou.aliyuncs.com/k8sth/kube-scheduler-amd64:v1.10.0 k8s.gcr.io/kube-scheduler-amd64:v1.10.0
docker tag registry.cn-hangzhou.aliyuncs.com/k8sth/etcd-amd64:3.1.12 k8s.gcr.io/etcd-amd64:3.1.12
docker tag registry.cn-shenzhen.aliyuncs.com/kubernetes_google/kubernetes-dashboard-amd64:v1.10.0 k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0

启动 Kubenetes

指引:https://kubernetes.io/docs/setup/minikube/#quickstart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 在代理下运行时,需要指定正确的代理,否则 minikube 在内部访问网络会有问题
# 注意,代理地址应当是在虚拟机中能够访问的地址,不能使用 127.0.0.1、localhost 这种
https_proxy=http://myproxy.com:8080
minikube start \
--docker-env http_proxy=http://myproxy.com:8080 \
--docker-env https_proxy=http://myproxy.com:8080 \
--docker-env no_proxy=192.168.99.0/24
--vm-driver=none

# 安装和启动过程中可能产生错误,通过该命令查看日志
minikube logs -f

# 启动 k8s( CentOS 上不使用任何 vm 驱动,MAC 上默认可使用 VirtualBox)
minikube start \
--network-plugin=cni \
--container-runtime=containerd \
--bootstrapper=kubeadm
--vm-driver=none

# Dashboard
# https://github.com/kubernetes/dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
kubectl proxy

# 部署及运行镜像
kubectl run hello-minikube --image=registry.cn-hangzhou.aliyuncs.com/acs/echoserver:1.4 --port=8080

# 导出服务
kubectl expose deployment hello-minikube --type=NodePort

# 查询 Pod
kubectl get pod
kubectl get pods --all-namespaces

# 查看状态
kubectl describe --namespace=kube-system po kubernetes-dashboard-6f4cfc5d87-d647l
kubectl logs kubernetes-dashboard-6f4cfc5d87-x976v --namespace=kube-system
kubectl cluster-info

# 调用服务
curl $(minikube service hello-minikube --url)

# 删除服务
kubectl delete services hello-minikube

# 删除部署
kubectl delete deployment hello-minikube

# 停止 k8s
minikube stop

向 kubernetes 添加账号

https://github.com/kubernetes/dashboard/wiki/Creating-sample-user

相关问题

failed to create kubelet: misconfiguration: kubelet cgroup driver: “cgroupfs” is different from docker cgr…driver: “systemd”

该问题因为 docker 的配置和 kubelet 的配置不一致导致。

使用 docker info 打印 docker 信息:

1
2
3
4
5
6
[root@VM_0_16_centos kubelet.service.d]# docker info | grep Driver
WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
WARNING: You're not using the default seccomp profile
Storage Driver: devicemapper
Logging Driver: journald
Cgroup Driver: systemd

而查看 kubelet 服务的启动参数(--cgroup-driver),其设置为 cgroupfs

1
2
3
4
5
6
7
8
9
10
11
[root@VM_0_16_centos kubelet.service.d]# more /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

[Unit]
Wants=docker.socket

[Service]
ExecStart=
ExecStart=/usr/bin/kubelet --hostname-override=minikube --cluster-domain=cluster.local --cgroup-driver=cgroupfs --authorization-mode=Webhook --client-ca-file=/var/lib/minikube/certs/ca.crt --fail-swap-on=false --kubeconfig=/etc/kubernetes/ku
belet.conf --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --cluster-dns=10.96.0.10 --cadvisor-port=0

[Install]

此时,修改 docker 的服务参数(vi /usr/lib/systemd/system/docker.service),将其中的 --exec-opt native.cgroupdriver 参数值改为 cgroupfs

然后,重启 docker,重启 kubelet

1
systemctl daemon-reload && systemctl restart docker && systemctl restart kubelet

[ERROR FileContent–proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1

解决方案:

1
2
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables

Unable to update cni config: No networks found in /etc/cni/net.d

1
yum install -y kubernetes-cni

参考

https://www.jianshu.com/p/a42eeb66a19c

我们在后端系统实现了 HTTP 请求的代理类,用于请求其他第三方系统。大致的请求流程是这样的:

![](/images/记一次 .NET Framework 不兼容 HTTP COOKIE 协议标准的问题跟踪-1.png)

消费系统不能直接请求业务系统的 HTTP 接口,需要由中间的 HttpHelper 代理请求。其中 HttpHelper 接受消费系统传入的各种参数,包括要请求的 URL、METHOD、HEAD、BODY 等,在实际生产中一直运行得很好,直到如下异常的出现:

1
2
System.Net.CookieException: Cookie format error.
at System.Net.CookieContainer.CookieCutter(Uri uri, String headerName, String setCookieHeader, Boolean isThrow)
阅读全文 »

引言

作为一个软件系统,需要写日志,这是不言而喻的,这是大家都会不假思索地说“那当然”的事。不论是什么语言,写日志的专用框架也不一而足,写到文本的,写到数据库的,写到队列的,写到Redis的等等等等。对于日志的几个级别,Trace、Debug、Warning、Error、Fault,大家也能够如数家珍。但是,有多少人能够回答下面这几个问题呢?

为什么需要写日志?
什么时候写日志?
日志是写给谁看的?
日志里都要写什么?
日志的组织形式应该怎样?

接下来,我尝试一一地解答这些问题,说说我的理解。

阅读全文 »

以下以 VS 的编译工具包为例,实际上 VS IDE 本身也可以如此进行。

一、下载在线安装文件

  1. 进入下载页:https://www.visualstudio.com/zh-hans/downloads/
  2. 选择最底部的 Other Tools and Frameworks -> Visual Studio 2017 生成工具 并下载。
  3. 以管理员身份运行刚刚下载的在线安装文件,注意带参数:--layout "F:\software\VS2017 BuildTool\Offline" --lang zh-CN

![](/images/创建 VS 2017 的离线安装包-1.png)

此时将开始下载安装所需文件:(如果断电断网或者关闭了下载窗口,没关系,输入命令重头来过,还是会继续下载的)

![](/images/创建 VS 2017 的离线安装包-2.png)

阅读全文 »

初中时,在电视里看office学习节目,对电脑无比神往。高二时,第一次开电脑上机课,两个人一台机学开机关机等基本操作,激动得大腿肌肉颤抖,在凳子上坐不住,坐两分钟蹲几分钟马步,实在会发抖,过了十几分钟才坐的住。这就是快感。

大学时,左边放着个水杯,码一阵代码后开启调试的间歇喝一口水,结果杯里的水喝完了,举着空杯喝一口空气。杯子放下继续码代码,直到第二次…第N次举着空水杯喝空气之后,仍然没有去把杯子续上,然而续水很远吗?不,水壶就在右手边。这就是快感。

临毕业,自己写一个博客程序,生生推倒重写3次,每一次都是质变。期间一个结构设计问题思考酝酿了很久,最终是半夜做梦突然来了灵感醒来,兴奋的再也睡不着了,马上一个激灵起来实现。整个博客程序完成之后无意看到了head first设计模式,各种我操我操的感叹,尼玛怎么跟我想的一样?这就是快感。

阅读全文 »

高性能

业务方面

  • 将同步业务转化为异步业务
  • 业务分级,柔性可用
  • 减少不必要的数据库请求
  • 业务解耦,降低关联性

应用方面

  • 前端高性能设计(略)
  • 使用缓存:多级缓存、分布式缓存
  • 预加载、懒加载、延迟初始化
  • 尽量减小交互接口数据包大小
  • 尽量减少序列化、对象克隆
  • 尽量减少跨进程、跨机器、跨网络访问
  • 尽量减少在同步业务中使用事务
  • 尽量减少锁的使用
    • 使用乐观锁
    • 尽量缩小锁的范围
    • 尽量将低性能逻辑放到锁的范围之外
  • 使用异步逻辑
  • 队列削峰,先接受,后处理
  • 尽量复用
    • 线程:线程池
    • 连接:长连接、连接池
阅读全文 »