利用TravisCI直接發佈靜態網頁到Github Pages上


github 有一個工具讓你可以存放一些簡單的靜態網頁

而且是完全免費!(當然有幾個附帶的條件)

  • 1GB容量
  • 只支持靜態網頁(html/css/js等)
  • 每月100GB流量

只要你在github的repo中放上你的網頁 (如index.html)
你就可以在 https://[username].github.io/[repo_name] 中看到你放上去的網站
亦可以設定一個首頁
只要repo的名字是 [username].github.io
你就可以直接在 https://[username].github.io 看到你的網站了

Read More

cert-manager-with-kubernetes-ingress


說起免費的HTTPS cert
很多人都會用let’s encrypt的服務
原因是簡單,易用
在VM上裝一個script然後簡單配置一下nginx就可以生成一張數個月的ssl certificate

但當來到kubernetes就有點麻煩
原因是你配置的服務很多可能都不在同一部機上
當你生成了一張ssl cert之後可能要手動去更新相應的配置
而且要建立自動更新難度更大

所以這時侯就可以用到cert-manager了
https://github.com/jetstack/cert-manager
他是一個k8s的addon
可以生成一系列的resources去幫以上的配置自動化
而且除了let’s encrypt之外也支持其他的ssl cert發行者

如果是用let’s encrypt的話
原理大致如下

首先你會生成一個ingress
並加一些特殊的annotation去表明你想cert-manager去幫你配置ssl cert
在這邊你需要先指定一個secret,讓cert-manager把配置好的ssl存放在裡面

之後cert-manager接收到相應的事件觸發後就會開始工作流程
他會先建立一張self-signed的ssl cert並放在該secret裡面
這個時侯你去訪問ingress就會發現https已經能夠使用
但ssl cert是不被瀏覽器信任的

然後cert-manager會建立一個暫時的ingress
去接收來自let’s encrypt的acme challenge
去證明你擁有該域名
如果驗證成功的話就會生成一張正確的ssl cert並更新secret
之後你再訪問https就會看到鎖頭了

實際操作這邊就懶得說了
直接看這裡
https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/index.html

有一點範例沒有說清楚
但卻至關重要,因為你如你是用nginx-ingress的話好有可能會出現這個問題

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
annotations:
certmanager.k8s.io/cluster-issuer: "letsencrypt-prod"
certmanager.k8s.io/acme-challenge-type: http01
certmanager.k8s.io/acme-http01-edit-in-place: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- a1.example.com
secretName: al-example-com-tls
rules:
- host: a1.example.com
http:
paths:
- path: /api
backend:
serviceName: backend
servicePort: 80

當中certmanager.k8s.io/acme-http01-edit-in-place: "true"
這句是很重要的

因為nginx-ingress是不能如時接受兩個ingress resources
就是如果你有兩個ingress,而兩個都有同一個host的話
只有其中一個能運行,另一個則無效
大概猜到原因是nginx的配置有關
因為nginx-ingress-controller會接收ingress的配置並且在/etc/nginx/conf.d中生成配置文件

而cert-manager預設是acme-challenger會生成另一個ingress資源出來
所以你要把這個配置設定成true,目的就是希望cert-manager去更改原本的ingress
且不是新開另一個出來

deploy-npm-package-with-travis


方法一: 利用travis內置的deploy provider

# Login the travis.com
travis login --com

# encrypt the API_KEY for travis API
travis encrypt [NPM_API_KEY] --com --add 'deploy.api_key'

這個命令會在.travis-ci.yaml中加入一個deploy的secret
若果是公開的repo最好把它抽出來以環境變數的形式去載入

但這個如果用環境變數的話不知為何總是跑出

Unauthorized you must be logged in to publish packages travis```

搞了一輪之後決定用第二個方法

## 方法二: deploy script及利用.npmrc

新增一個deploy.sh
```bash
echo "//registry.npmjs.org/:_authToken=${NPM_API_TOKEN}" > $HOME/.npmrc

npm publish

這會將環境變數寫成npmrc
而npm script會利用它來認證並發佈

檔案如下

language: node_js
node_js:
- '11'
- '10'
- '8'
stages:
- test
- name: deploy
if: branch = master
cache: npm
# Use script instead of npm provider as it cannot auth via env variables?
deploy:
provider: script
script: "./deploy.sh"
skip_cleanup: true
# only on tagged builds
on:
tags: true
# Send an email when a new version is released
notifications:
email:
recipients:
- "$NPM_EMAIL"
on_success: change
on_failure: always

參考

-

gRPC在kubernetes的小問題


事緣每隔一段時間deploy後
總有一部份pod在連接其他pod的gRPC時會報錯
發生機率極低

經過一大堆的測試後卻又不能復現
包括各種DNS/k8s上的測試

但我查看kube-proxy的log後
相信是跟gRPC內置的dns cache機制有關係
因為每次狀態發生時都跟kube-proxy的重啟有關係
因為未明原因導致kube-proxy重啟 > 重啟後一些routing的改變 >
某些pod的internal ip改變了 > gRPC的DNS仍舊指向舊的pod ip > 連不上

用比較暴力的方法去解決
就是利用gRPC的DEADLINE機制
再加上設定liveness probe
每隔一段時間k8s會訪問你的狀態
若果是連續幾次都timeout的話就會把pod砍掉重啟


const deadline = new Date().setSeconds(new Date().getSeconds() + GRPC_TIMEOUT_SECONDS);
gRPCClient.query(query, { deadline }, (err, res) => {
...
})

當然上面是一個很危險的方法
若果連線狀態很差可能會一直重啟
造成服務不穩的情況
更好的做法或者是利用第三方的service discovery
例如Istio或者linkerd等service mesh
或者將來有時間可以再研究一下…

參考

選擇kubenetes的node type


公司的集群一直都在用t2.medium
原因是t2系列中可累積的CPU credit非常實用
詳情可參看 AWS中t2.medium的二三事
而且medium的內存(4G)也夠跑一定數量的pod
比較比相當不錯

但最近參考了其他人的做法
把node type從medium轉換成xlarge之後
node的數量大減之餘,價格亦有相當的減少
所以希望在此分享一下心得

為什麼t2.xlarge會比t2.medium好

如果單看價錢的話
t2.xlarge的價錢是t2.medium的4倍
但只有2倍於medium(4個vCPU), cpu credit也沒有去到4倍

這樣看的話只有內存才算是真的4倍
那為什麼說xlarge會比medium利用率更好呢?

Read More

把blog由wordpress轉移到hexo(下)


Hexo小心得

從wordpress直接導入

安裝plugin

npm install --save-dev hexo-migrator-wordpress

注意這個plugin並不會把圖片自動下載
我是另外寫了一個script把圖片都下載並加入到項目當中
好一點當然是上傳到一些永久的空間(如cloudinary之類)

SEO配置

加入sitemap及rss feed

npm install --save-dev hexo-generator-feed
npm install --save-dev hexo-generator-sitemap

當然每個post你也應該設定一個好的slug及相關的tags

## 自訂theme

安裝hexo時就已經預載了一個theme於目錄./themes/ 中
最簡單的方法就是直接修改
或者可以使用其他人所寫的theme

摘要excerpt

在文章中加入以下script會自動生成文章摘要

<!-- more -->

Facebook留言

安裝plugin

npm install --save-dev hexo-fbcomments

修改_config.yaml

# Enable facebook comments
fbcomments:
enabled: true
lang: zh_HK
appId: [facebook_app_id]
numPosts: 20

發佈到github pages

先建立相應的github repo並新增一個orphan branch
可以看這裡

然後安裝plugin

npm install --save-dev hexo-deployer-git

更改_config.yaml

# Deployment
# Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo: git@github.com:[username]/[reponame].git
branch: gh-pages
message:

利用command發佈

hexo generate --deploy

把blog由wordpress轉移到hexo(上)


最近把這個blog由wordpress轉移到github pages上
同時亦利用了hexo來生成靜態網站
運行了一段時間後十分滿意
所以在此發表一下心得

原因

Wordpress作為世界上最多人用的blog/cms系統
作為一個blog在功能上當然沒有任何不足
基本的SEO/CMS/Migrate功能已經有足夠的支持
但在我而言仍有部分不足之處

  • 缺乏版本控制
  • 完整備份不算簡單(尤其是圖片)
  • 需要數據庫
  • 容易成為攻擊的目標

因為我經常會把東西搬來搬去
e.g. 由自己家的服務器 > Digital Ocean > GKE > GCP
每次需要搬blog的時侯就要找個plugin 把blog的內容導出再導入
還要擔心圖片沒搬遷成功 (有可能export出來的blog只把圖片導出成連結)
而且自己架的數據庫要定期做備份等等…

Read More

清除docker主機上的垃圾


如果你在本機上有docker build,或者你的CI有用到docker build的時侯
每過一段時間就會發現佔用的空間會大得很誇張
原因是docker build的時侯會下載各種的base image,更甚者會建立各樣的fs layer
而且建立了的image/fs layer是不會主動去刪掉的
所以就需要設立一些cronjob 去定期把沒用/舊的東西刪掉去騰出更多的空間

Read More

當elasticsearch硬碟滿了


不小心把dev場gRPC的debug log打開了,導致每天產生了差不多800萬條event
把本來就剩不了多少的空間直接塞爆了,碰巧prometheus跟logstash在同一個節點上
prometheus不幸地掛掉了導致連訊息也沒收到
過了兩三天才發覺數據沒了才發現出事

最後要搞了兩天才把數據回復
幸運的是開始時就已經設置了一些機制去防錯
因此這次才沒有發展成為災難性的事件
就寫了以下的一些分享

Read More