2021年4月30日金曜日

Grafana を helm chart で構築してみた

Grafana を helm chart で構築してみた

環境

Grafana を helm chart で k8s 上に構築してみました
アクセスには NodePort を使います

環境

  • kubernetes 1.20.4
  • helm 3.5.2
  • Grafana helm chart 6.7.4

Grafana の helm repo の インストール

  • helm repo add grafana https://grafana.github.io/helm-charts
  • helm repo update

普通に使う

まずは普通に使います
構築して NodePort でアクセスしてみます

  • helm install my-release grafana/grafana --set service.type=NodePort
  • kubectl get svc
AME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE  
kubernetes           ClusterIP   10.96.0.1        <none>        443/TCP        14d  
my-release-grafana   NodePort    10.107.144.202   <none>        80:32483/TCP   8m45s

grafana の Pod がデプロイされたノードの IP を調べます
そして http://node-ip:32483 にアクセスすると Grafana の UI が表示されることが確認できます

ログインする

admin ユーザにでログインします
パスワードは secret に登録されているので以下のコマンドで取得できます

  • kubectl get secret --namespace default my-release-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

ingress 経由で使う

よくあるケースは ingress 経由で使う場合です
ポイントは ingress.hosts と ingress.path で宛先を設定する点です
またサブディレクトリでアクセスしたい場合は serve_from_sub_path を使います

  • vim values.yml
grafana.ini:  
  server:  
    protocol: http  
    domain: localhost  
    root_url: "%(protocol)s://%(domain)s:3000/-/grafana"  
    serve_from_sub_path: true  
ingress:  
  enabled: true  
  hosts:  
    - "grafana.example.com"  
  path: "/-/grafana"  
service:  
  type: NodePort  
  nodePort: 32080

set だと長くなるなるので設定は values.yml を使っています

デプロイしてみましょう

  • helm install my-release grafana/grafana -f values.yml

これで http://node-ip:32080 にアクセスすれば Grafana にアクセスできます
ログイン方法は先程紹介したとおりです

最後に

ログインでリダイレクトされる場合は cookies を削除しましょう

参考サイト

2021年4月29日木曜日

Gitlab CI で YAML ファイルを include したりテンプレート化したりする方法

Gitlab CI で YAML ファイルを include したりテンプレート化したりする方法

概要

.gitlab-ci.yml が複雑になると YAML ファイルの内容が冗長化することがあります
そんな場合は include や anchor 機能を使えば YAML ファイルの管理が楽になったりします

環境

  • Gitlab 13.9.5-ee

include を使う

include を使うとジョブの定義を別の YAML に定義しそれを使用することができるようになります

  • mkdir .gitlab-ci
  • vim .gitlab-ci.yml
stages:
  - stage1
  - stage2

include:
  - local: /.gitlab-ci/echo1.yml
  - local: /.gitlab-ci/echo2.yml
  • vim .gitlab-ci/echo1.yml
echo1:
  image:
    name: alpine:latest
  stage: stage1
  script:
    - "export MSG=hello"
    - "echo ${MSG}"
    - echo "MSG=HELLO" >> build.env
  artifacts:
    reports:
      dotenv: build.env
  • vim .gitlab-ci/echo2.yml
echo2:
  image:
    name: alpine:latest
  stage: stage2
  script:
    - "echo ${MSG}"
  dependencies:
    - echo1

dotenv を使ってジョブ間で値を渡すこともできます

テンプレート化する

テンプレート化した YAML の内容は継承っぽいことができるようになります
こちらはファイル (ジョブ) を分けるというより script を分ける場合などに使います

  • vim .gitlab-ci.yml
stages:
  - stage1
  - stage2

.echo1_script: &echo1_script
  - "export MSG=hello"
  - "echo ${MSG}"
  - "export MSG=HELLO"

.echo2_script: &echo2_script
  - "echo ${MSG}"

echo:
  image:
    name: alpine:latest
  stage: stage1
  script:
    - *echo1_script
    - *echo2_script

継承させたい script の内容はドットから始まるようにします
また anchor で名前を付与する必要があり名前はアンパサンドで参照名を付与します
参照する場合はアスタリスクでテンプレートを参照できます

参考サイト

2021年4月28日水曜日

Gitlab CI でステージ間で変数を共有する方法

Gitlab CI でステージ間で変数を共有する方法

環境

  • Gitlab 13.9.5-ee

.gitlab-ci.yml

答え: dotenv と dependencies を使います

stages:
  - stage1
  - stage2

echo1:
  image:
    name: alpine:latest
  stage: stage1
  script:
    - "export MSG=hello"
    - "echo ${MSG}"
    - echo "MSG=HELLO" >> build.env
  artifacts:
    reports:
      dotenv: build.env

echo2:
  image:
    name: alpine:latest
  stage: stage2
  script:
    - "echo ${MSG}"
  dependencies:
    - echo1

参考サイト

2021年4月27日火曜日

対策方法 Guideline 2.2 - Performance - Beta Testing

対策方法 Guideline 2.2 - Performance - Beta Testing

概要

スクリーンショットやアプリ内の文章に test や demo などのフレーズが含まれると「Guideline 2.2 - Performance - Beta Testing」でリジェクトされます
今回は自分の対策方法を紹介します

環境

  • Swift5
  • Xcode 12.4 (12D4e)

スクリーンショット内に Test などの文字が含まれていてもダメ

審査時にはアプリのスクリーンショットを含める必要がありますが、そのスクリーンショット内で「test」などのフレーズが使われていてもダメになります
例えばテキストフィールドなどでユーザを登録する場合に「testuser01」などを使ってスクリーンショットを取得した場合でもアウトになります
意味合いが違くても「test」というフレーズが含まれているのでリジェクトされるので使わないようにしましょう

Admob のテスト広告でもダメ

シミュレータで Admob を取得すると「Test mode」という文字が広告に含まれます
これもリジェクトされるようなのでアプリ内に広告がありかつシミュレータを使っている場合は広告が表示されないようにしてスクリーンショットを撮影しましょう

2021年4月26日月曜日

UIBarButtonItem の title が変わらない場合にチェックする箇所

UIBarButtonItem の title が変わらない場合にチェックする箇所

概要

IBOutlet で参照している UIBarButtonItem の title を変更する場合は button.title = "hoge" のようにします
しかしなぜか変わらないケースがあったので対処方法を紹介します

環境

  • Swift5
  • Xcode 12.4 (12D4e)

title を変更するサンプルコード

例えば以下のようなコードがあるとします
本来であれば Edit <-> End とタイトルが変わります

@IBAction func edit(_ sender: AnyObject) {
    if (self.tableView.isEditing) {
        self.tableView.isEditing = false
        editButton.title = "Edit"
    } else {
        self.tableView.isEditing = true
        editButton.title = "End"
    }
}

StoryBoard で BarButtonItem の設定を確認する

原因は BarButtonItem の属性でした
StoryBoard 上で「System Item」の値を Custom に変更したところちゃんとタイトルが動的に変更されるようになりました

StoryBoard 上で Title 属性をあらかじめ設定しておくと System Item も自動的に Custom に変更されるようです

2021年4月25日日曜日

Swift5 適当な箇所をタップしてキーボードを非表示にする方法

Swift5 適当な箇所をタップしてキーボードを非表示にする方法

概要

テキストフィールドなどをタップするとソフトウェアキーボードが表示され入力することができます
キーボードを非表示にする場合は Entry をタップするか別のテキストフィールドにフォーカスを変更する必要があります
それだとかなり UX が悪いので適当な箇所をタップした際にキーボードが消えるようにする方法を紹介します

環境

  • Swift5
  • Xcode 12.4 (12D4e)

UIViewController の extension を作成する

どこでもいいので以下のコードを書き加えます
トップページの UIView クラスの先頭などが良いと思います
必ず class の外に記載するようにしてください

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false            
        view.addGestureRecognizer(tap)
    }
    @objc func dismissKeyboard() {
        view.endEditing(true)
    }
}

viewDidLoad で呼び出す

先程定義した extension を viewDidLoad で呼び出します
当然ですが UIView を継承している View の viewDidLoad 関数内で呼び出してください

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
}

参考サイト

2021年4月24日土曜日

[Swarm] docker stack deploy で Blue-Green deployment の方法を考える

[Swarm] docker stack deploy で Blue-Green deployment の方法を考える

概要

docker swarm 上で Blue-Green デプロイを実現する方法を考えみました
stack deploy を使ってアプリを 2 つ用意しそれを LB などを使って切り替える方法を考えます

今回は 2 ノードの Swarm 環境 (192.168.100.10, 192.168.100.11) で試します
Swarm 環境はローカルではなくリモート先にあるものとします

環境

  • Ubuntu 18.04
  • docker 19.03.13
  • Ruby 3.0.0
  • MySQL 8.0.24

テスト用のアプリ作成

分かりやすいようにデータベースを使った Web アプリを作成します
データベースはそのままでアプリのみを Blue-Green デプロイメントで切り替えます

Web アプリ

  • bundle init
  • vim Gemfile
gem "thin"
gem "rake"
gem "mysql2"
gem "sinatra"
gem "sinatra-contrib"
gem "sinatra-activerecord"
  • bundle install

アプリは Blue or Green のどちらに振り分けられているかわかるようにしておきます
また DB は手動で作成するのでマイグレーションファイルは作成しません

  • vim app.rb
require 'sinatra'
require 'sinatra/json'
require "sinatra/activerecord"
require './models/user.rb'
class DBTestApp < Sinatra::Base
  register Sinatra::ActiveRecordExtension
  get '/all' do
    @users = User.all
    deployment = ENV["DEPLOYMENT"] || "blue"
    ret = {
      deployment => @users
    }
    json ret
  end
end
  • vim config.ru
require './app'
run DBTestApp

database.yml

  • mkdir config
  • vim config/database.yml
development:
  adapter: mysql2
  database: test
  host: 192.168.100.200
  username: root
  password: xxxxxx
  encoding: utf8

データベースの準備

データベースは Swarm とは別の環境 (192.168.100.200) に配置してあることを想定しています
以下はコンテナで動作させていますがコンテナでなくても構いません

  • mkdir initdb.d
  • vim initdb.d/test.sql
DROP SCHEMA IF EXISTS test;
CREATE SCHEMA test;
USE test;
DROP TABLE IF EXISTS users;
CREATE TABLE users (
  id       INT(10) NOT NULL AUTO_INCREMENT,
  name     VARCHAR(40),
  age      INT(10),
  PRIMARY KEY (id)
);
INSERT INTO users (name, age) VALUES ("hawk", 10);
INSERT INTO users (name, age) VALUES ("snowlog", 20);
  • docker run -d -v $(pwd)/initdb.d:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=xxxxxx -p 3306:3306 --name db mysql:latest --default-authentication-plugin=mysql_native_password
  • mysql -h 192.168.100.200 -u root -p

こんな感じでアクセスしてデータがあれば OK です

--default-authentication-plugin=mysql_native_password は MySQL8 なので設定しています
これを設定しないと以下のエラーが発生します
ActiveRecord::ConnectionNotEstablished - Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

docker-compose.yml

  • vim Dockerfile
FROM ruby:3

WORKDIR /app
ADD . /app

RUN bundle config path vendor
RUN bundle install

EXPOSE 9292

CMD ["bundle", "exec", "rackup", "config.ru", "-o", "0.0.0.0"]

dockerignore を用意しないと開発サーバでビルドした mysql2 の shared object ファイルが配置されてしまいエラーになるので vendor ファイルは外します

  • vim .dockerignore
vendor/

Blue 用と Green 用を作成します
デプロイするコンテナは各ノードに配置されるようにします

  • vim docker-compose-blue.yml
version: "3.8"
services:
  web:
    image: registry:5000/root/web:latest
    ports:
      - "9292:9292"
    environment:
      DEPLOYMENT: blue
    deploy:
      mode: replicated
      replicas: 2
      placement:
        max_replicas_per_node: 1
  • vim docker-compose-green.yml
version: "3.8"
services:
  web:
    image: registry:5000/root/web:latest
    ports:
      - "9291:9292"
    environment:
      DEPLOYMENT: green
    deploy:
      mode: replicated
      replicas: 2
      placement:
        max_replicas_per_node: 1

ポイントは Green 側の LISTEN ポートは 9291 にする点です
こうすることで同一の docker swarm 上に Blue と Green の両方のアプリをデプロイできるようにします

イメージについて

今回はリモートの docker swarm 環境を使うのでイメージをビルドして事前にプライベートリポジトリに push しています
もしプライベートリポジトリがない場合は各 swarm のノードにログインしてそれぞれでビルドしても OK です

LB の準備

今回は nginx を使います
またコンテナで動作させます
ここはクラウドロードバランサや haproxy など代用できるものなら何でも OK です
ポイントはポートでバランシング先を切り替える点です

とりあえず Blue (9292) にバランシングするようにします

  • vim default.conf
upstream web {
  server 192.168.100.10:9292;
  server 192.168.100.11:9292;
}

server {
  listen 80;
  location / {
    proxy_pass http://web;
  }
}

動作確認

まずは Blue と Green のアプリをデプロイします
ノードに直接アクセスして両方のアプリが動作していることを確認します

  • docker -H 192.168.100.10:2376 stack deploy blue -c docker-compose-blue.yml --with-registry-auth
  • docker -H 192.168.100.10:2376 stack deploy green -c docker-compose-green.yml --with-registry-auth

次に LB となる nginx を起動します

  • docker run -d -p 80:80 -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf --name web nginx

これで nginx にアクセスすると blue のアプリからレスポンスが返ってきます

  • curl localhost/all

=> {"blue":[{"id":1,"name":"hawk","age":10},{"id":2,"name":"snowlog","age":20}]}

次に green のアプリ (9291) に切り替えてみます

upstream web {
  server 192.168.100.10:9291;
  server 192.168.100.11:9291;
}

server {
  listen 80;
  location / {
    proxy_pass http://web;
  }
}
  • docker restart web
  • curl localhost/all

=> {"green":[{"id":1,"name":"hawk","age":10},{"id":2,"name":"snowlog","age":20}]}

このような感じで LB となっているコンポーネントで振り先変更するだけでアプリのデプロイを完了することができます

最後に

今回は 1 つの Swarm 環境で Blue-Green デプロイメントする方法を紹介しましたが Swarm 環境を複数用意しても OK です
その場合は LB 側でバランシングする際にポートバランシングだけではなく IP や FQDN などで別の Swarm に向けるようにしてください

ポイントは

  • ステートフルなコンポーネントは外部に配置する
  • Blue-Green デプロイメントに含めるコンポーネントはステートレスなコンポーネントにする

かなと思います

2021年4月23日金曜日

The Google Mobile Ads SDK was initialized without AppMeasurement

The Google Mobile Ads SDK was initialized without AppMeasurement

概要

Admob を最新版にしたらエラーが発生したので対応しました

環境

  • Swift5
  • Xcode 12.4 (12D4e)
  • Firebase/AdMob 7.10.0

Info.plist の修正

設定する値や方法はエラー文内にもある公式のヘルプページがわかりやすいです

GADApplicationIdentifier を追加する

Admob の管理画面で確認できるアプリID を値に設定しましょう

SKAdNetworkItems を追加する

Ad Network 用のあらかじめ Google 側で用意された ID を登録する必要があります
Array + Dict 形式で登録しましょう

GADIsAdManagerApp を追加する

これは公式のヘルプページに記載がなかったのですが追加する必要がありました
boolean で YES を登録すれば OK です

Xcode での編集が面倒なら直接開いて編集しても OK

特に SKAdNetworkItems はアイテムの数が多いので UI でポチポチ追加するのは面倒です
テキストを直接編集したほうが簡単です
インデントなどは Xcode が勝手にやってくれるので自分で修正しなくても OK です

2021年4月22日木曜日

Initialization of 'UnsafePointer' results in a dangling pointer

Initialization of 'UnsafePointer<UInt8>' results in a dangling pointer

概要

Swift5 に対応したら UnsafePointer を生成する部分で警告が表示されるようになったので対応しました

環境

  • Swift5
  • Xcode 12.4 (12D4e)

警告されるコード

let start = Data(bytes: UnsafePointer<UInt8>([0xFF, 0xFF, 0xFF, 0xFF, 0xFF] as [UInt8]), count: 5)

Data を生成するのに UnsafePointer を使っていました
これを警告が出ないように修正しました

対応したコード

let bytes = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 1)
bytes.storeBytes(of: 0xFFFF_FFFF, as: UInt32.self)
let start = Data(bytes: bytes, count: 4)

UnsafeMutableRawPointer を生成しそこから Data を生成するように変更しました
これで警告は表示されなくなりました

参考サイト

2021年4月21日水曜日

Gitlab CI から MergeRequest を作成する方法

Gitlab CI から MergeRequest を作成する方法

概要

前回は Gitlab CI から branch を作成してみました
今回は作成した branch を元に MergeRequest を作成してみます

環境

  • Gitlab 13.9.5-ee
  • Ubuntu 18.04
  • docker 19.03.6

create_mr.sh の作成

MergeRequest は Gitlab の API をコールします
公式のスクリプトがあったのでそれを流用しています
master に対して MergeRequest を作成するので TARGET_BRANCH は固定にしています
MergeRequest のタイトルや本文は API のドキュメントを読んで好きなように設定してください

#!/usr/bin/env bash
# Extract the host where the server is running, and add the URL to the APIs
[[ $HOST =~ ^https?://[^/]+ ]] && HOST="${BASH_REMATCH[0]}/api/v4/projects/"

# Look which is the default branch
TARGET_BRANCH="master"

# The description of our new MR, we want to remove the branch after the MR has
# been closed
BODY="{
    \"id\": ${CI_PROJECT_ID},
    \"source_branch\": \"${CI_COMMIT_REF_NAME}\",
    \"target_branch\": \"${TARGET_BRANCH}\",
    \"remove_source_branch\": true,
    \"title\": \"WIP: ${CI_COMMIT_REF_NAME}\",
    \"assignee_id\":\"${GITLAB_USER_ID}\"
}";

# Require a list of all the merge request and take a look if there is already
# one with the same source branch
LISTMR=`curl --silent "${HOST}${CI_PROJECT_ID}/merge_requests?state=opened" --header "PRIVATE-TOKEN:${PRIVATE_TOKEN}"`;
COUNTBRANCHES=`echo ${LISTMR} | grep -o "\"source_branch\":\"${CI_COMMIT_REF_NAME}\"" | wc -l`;

# No MR found, let's create a new one
if [ ${COUNTBRANCHES} -eq "0" ]; then
    curl -X POST "${HOST}${CI_PROJECT_ID}/merge_requests" \
        --header "PRIVATE-TOKEN:${PRIVATE_TOKEN}" \
        --header "Content-Type: application/json" \
        --data "${BODY}";

    echo "Opened a new merge request: WIP: ${CI_COMMIT_REF_NAME} and assigned to you";
    exit;
fi

echo "No new merge request opened";

.gitlab-ci.yml の作成

branch を作成してから MergeRequest を作成します
全体のコードは以下のようになります

stages:
  - create_branch

create_branch:
  image:
    name: alpine/git:latest
    entrypoint: [""]
  stage: create_branch
  before_script:
    - "git config --global user.name root"
    - "git config --global user.email root@mail.domain"
    - "git config --global credential.helper store"
    - "echo https://${GIT_USER}:${GIT_PASSWORD}@gitlab.example.com > ~/.git-credentials"
    - "apk add curl"
    - "apk add bash"
    - "export PROJECT_ID=3947"
  script:
    # Create a branch
    - "git clone https://gitlab.example.com/root/test.git"
    - "cd test"
    - "export LATEST_SHA=$(git show -s --format=%h)"
    - "git checkout -b test_from_${LATEST_SHA}"
    - "git push -u origin test_from_${LATEST_SHA}"
    # Create a merge request
    - "cd $CI_BUILDS_DIR/$CI_PROJECT_PATH"
    - "chmod +x ./create_mr.sh"
    - "HOST=${CI_PROJECT_URL} CI_PROJECT_ID=${PROJECT_ID} CI_COMMIT_REF_NAME=test_from_${LATEST_SHA} GITLAB_USER_ID=${GITLAB_USER_ID} PRIVATE_TOKEN=${GIT_PASSWORD} ./create_mr.sh"

説明

branch と MergeRequest を作成するリポジトリは CI を回すリポジトリとは別のリポジトリを想定しています

まずブランチを作成します
これは前回の方法と同じになります

そしてそのブランチを元に Merge Request を作成します
事前に作成したシェルスクリプトに必要な環境変数を渡しています
CI_PROJECT_URL, GITLAB_USER_ID は Gitlab 側で事前に準備してある変数になります
PROJECT_ID は MergeRequest を作成するプロジェクトの ID になります
これはプロジェクトの設定ページから確認できるので固定で指定します
PRIVATE_TOKEN は clone 時にトークン認証にしているのでそのトークンをそのまま使えます

今回はこれくらいの変数しか準備していませんが作成する MergeRequest の本文やアサインに合わせて適宜変更してください

動作確認

git push して CI を回して問題なく MergeRequest が作成されれば OK です

最後に

実際に動作するようになるまではトライアンドエラーを繰り返しましょう

2021年4月20日火曜日

Gitlab helm chart で外部のオブジェクトストレージサービスを使う方法

Gitlab helm chart で外部のオブジェクトストレージサービスを使う方法

概要

Gitlab helm chart はデフォルトだと minio を使う設定になっています
minio を無効にして外部のオブジェクトストレージを使うことができます
今回は minio は有効にしつつファイルのアップロード部分だけど外部のオブジェクトストレージにする方法を紹介します

環境

  • kubernetes 1.20.4
  • helm 3.5.2
  • Gitlab helm chart 4.10.3

secret の追加

s3 や gcs などに接続するための認証情報を secret に格納します
connection というキーに認証情報を確認します

  • vim s3.yml
provider: AWS
region: us-east-1
aws_access_key_id: xxxx
aws_secret_access_key: xxxx
aws_signature_version: 4
endpoint: https://s3.us-east-1.amazonaws.com
  • kubectl create secret generic gitlab-registry-os-secret -n gitlab --from-file=connection=s3.yml

values の追加

以下の設定を追加します
先程追加した認証情報を appConfig.uploads.connection.secret で参照します
connection キーは global.appConfig.uploads.connection.key 側で指定します
アップロード先のバケット名は global.appConfig.uploads.bucket で指定します
事前にバケットは作成しておきましょう

--set global.minio.enabled=true \  
--set global.appConfig.uploads.bucket=uploads \  
--set global.appConfig.uploads.connection.secret=gitlab-registry-os-secret \  
--set global.appConfig.uploads.connection.key=connection

あとは helm upgrade などを実行すれば OK です

uploads 以外も外部のオブジェクトストレージにしたい場合は

例えば registry の情報などを外部のオブジェクトストレージにしたい場合は global.registry.bucketregistry.storage.secret などを同じように設定します
同じ接続先を使う場合は認証情報は 1 つで OK なので同じ secret を参照するようにしてください

他の設定方法のサンプルはこちらにあるので参照してみてください
https://gitlab.com/gitlab-org/charts/gitlab/blob/master/examples/values-external-objectstorage.yaml

認証情報だけを書き換えた場合は

例えばリージョンや認証情報を変更したい場合は secret を更新します
その場合は Gitlab の webservice Pod を再起動する必要があります

  • kubectl rollout restart deploy gitlab-webservice-default -n gitlab

参考サイト

2021年4月19日月曜日

Gitlab CI から branch を作成する方法

Gitlab CI から branch を作成する方法

概要

Gitlab CI から特定のリポジトリに対して branch を作成する方法を紹介します
ポイントは認証部分かなと思います

環境

  • Gitlab 13.9.5-ee
  • Ubuntu 18.04
  • docker 19.03.6

runner の準備

今回はコンテナで起動しています
gitlab-runner のコンテナでの起動方法はこちらで紹介しています

CI の変数設定

git にアクセスするための認証情報を Gitlab の CI の変数設定に登録します
リポジトリの Settings -> CI/CD -> Variables から登録します
今回は git に対してパスワード認証するので登録していますが鍵認証を使う場合は少しやり方が異なるので注意してください

  • GIT_USER・・・ git push するユーザ
  • GIT_PASSWORD・・・ git push するユーザのパスワード

Gitlab の場合トークン認証を使うこともできます
その場合は GIT_USER には oauth2 というユーザ名を設定しましょう

.gitlab-ci.yml の作成

本題の .gitlab-ci.yml を作成します
使用するイメージは git コマンドが使える必要があります
今回は alpine/git を使っていますが git コマンドが使えれば何でも OK です

stages:
  - create_branch

create_branch:
  image:
    name: alpine/git:latest
    entrypoint: [""]
  stage: create_branch
  before_script:
    - "git config --global user.name root"
    - "git config --global user.email root@mail.domain"
    - "git config --global credential.helper store"
    - "echo https://${GIT_USER}:${GIT_PASSWORD}@gitlab.example.com > ~/.git-credentials"
  script:
    - "git clone https://gitlab.example.com/root/test.git"
    - "cd test"
    - "export LATEST_SHA=$(git show -s --format=%h)"
    - "git checkout -b test_from_${LATEST_SHA}"
    - "git push -u origin test_from_${LATEST_SHA}"

説明

git の認証情報は credential.helper を使って事前に登録しておきます
この方法でなくても良いですがファイルに認証情報を書けば勝手にしようしてくれるのでこのようにしています

ブランチを作成するリポジトリは CI を実行するリポジトリ位ではなく別のリポジトリを clone して持ってきています
ブランチを作成するリポジトリが CI を実行しているリポジトリなのであれば clone の必要はありません
また clone するので clone 先のリポジトリに clone する権限がある必要があります

ブランチ名は何でも OK ですが今回は変数として最新のコミットハッシュを入れています

動作確認

push して CI を実行してみましょう
ブランチが作成されていれば OK です

最後に

次回は作成した branch を元に Gitlab CI から MergeRequest を作成してみます

2021年4月18日日曜日

Gitlab helm chart で Gitaly Cluster を構成してデプロイする方法

Gitlab helm chart で Gitaly Cluster を構成してデプロイする方法

概要

デフォルトのデプロイ方式だと Praefect がデプロイされず Gitaly もシングル構成でデプロイされます
今回は Praefect を有効にして Gitlab helm chart を使って Gitaly Cluster を構築してみました
なお、現在の Gitlab helm chart (4.10.3) では Gitaly Cluster 単体でデプロイすることはできないので必ず Gitlab と合わせてデプロイする必要があります

環境

  • kubernetes 1.20.4
  • helm 3.5.2
  • Gitlab helm chart 4.10.3

コマンド全体

helm install gitlab gitlab/gitlab --namespace gitlab --timeout 600s \
--set global.hosts.domain=gitlab.example.com \
--set global.gitlabVersion=13.10.2 \
--set nginx-ingress.controller.hostNetwork=true \
--set nginx-ingress.controller.service.type="" \
--set nginx-ingress.controller.kind=DaemonSet \
--set nginx-ingress.controller.service.externalTrafficPolicy="" \
--set global.praefect.enabled=true \
--set global.praefect.virtualStorages[0].name=default \
--set global.praefect.virtualStorages[0].gitalyReplicas=4 \
--set global.praefect.virtualStorages[0].maxUnavailable=2

hostNetwork を使う設定にしていますが不要であれば削除してください

Gitaly Cluster を構築するためのパラメータ

今回の肝となるパラメータは以下の 4 つです
まず praefect を ON にする必要があるので enabled=true は必須です
他の 3 つパラメータはクラスタ内にデプロイする gitaly の Pod の数になります
今回は 4 つデプロイする設定にしています
Gitaly Cluster では virtualStorages 名を決める必要があります
default という virtualStorages が必ず 1 つは必要になるので今回は default だけ作成しています
virtualStorages を追加したい場合は配列のインデックスを 1 にして name=vs2 などにして gitalyReplicas と maxUnavailable の値を設定すれば OK です

--set global.praefect.enabled=true \
--set global.praefect.virtualStorages[0].name=default \
--set global.praefect.virtualStorages[0].gitalyReplicas=4 \
--set global.praefect.virtualStorages[0].maxUnavailable=2

Postgres データベースに必要な値を投入する

Gitaly Cluster をデプロイすると最初は sql open: pq: password authentication failed for user "praefect" となり Gitaly Cluster は起動しません
これは Postgres に praefect 用のユーザとロールが存在しないためで現在の helm chart だとユーザとロール情報は手動で設定する必要があります
また Postgres が VM や RDS などで外部にある場合はコマンドが多少変わるので完了に合わせてユーザやロールを作成してください
以下は Pod でデプロイした Postgres に対してユーザとロールを追加する場合のコマンドです

直接コンテナにログインして SQL コマンドを実行する感じになります

# kubectl get secret gitlab-praefect-dbsecret -n gitlab -o jsonpath="{.data.secret}" | base64 --decode
# kubectl exec -it $(kubectl get pods -n gitlab -l app=postgresql -o custom-columns=NAME:.metadata.name --no-headers) -n gitlab -- bash
Defaulting container name to gitlab-postgresql.
Use 'kubectl describe pod/gitlab-postgresql-0 -n gitlab' to see all of the containers in this pod.
I have no name!@gitlab-postgresql-0:/$ PGPASSWORD=$(cat $POSTGRES_POSTGRES_PASSWORD_FILE) psql -U postgres -d template1
psql (11.9)
Type "help" for help.

template1=# CREATE ROLE praefect WITH LOGIN;
CREATE ROLE
template1=# \password praefect
Enter new password:
Enter it again:
template1=# CREATE DATABASE praefect WITH OWNER praefect;
CREATE DATABASE
template1=# \q
I have no name!@gitlab-postgresql-0:/$ exit
exit

動作確認

  • kubectl get pod -n gitlab

gitlab-gitaly-default-0 から gitlab-gitaly-default-3 までが問題なく起動しているのと gitlab-praefect-0, gitlab-praefect-1 が起動していれば Gitaly Cluster の構築が完了していることになります

あとは Gitlab にアクセスして git push ができるのも確認しても良いと思います

最後に

Gitaly の helm chart が Gitlab の helm chart から完全に分離されて個別にデプロイできるようになるともっと便利になるかなと思いました

参考サイト

2021年4月17日土曜日

公開されている helm chart をデバッグしてみよう

公開されている helm chart をデバッグしてみよう

概要

Helm chart は基本的に公開されています
マニフェストも見えるので挙動がおかしい場合には手元にマニフェストをダウンロードしてデバッグしてみましょう

環境

  • Helm 3.5.2

マニフェストをダウンロードする

helm pull を使います

  • helm pull gitlab/gitlab

これで tgz ファイルがダウンロードできます

chart を解凍する

手元で動作させるために解凍しましょう

  • tar zvxf gitlab-4.10.2.tgz

手元の chart を元に実行してみる

マニフェストが手元に来たのでそれを元に実行できるか試してみましょう

  • helm install test ./gitlab

必要なパラメータは適宜設定してください

chart を書き換えて print デバッグしてみる

これで直接 chart を書き換えることができます
例えばテンプレート情報が正しく設定されているか調べる場合にはコメントを使ってテンプレートの値を表示することができます

  • vim gitlab/charts/gitlab-runner/templates/_env_vars.tpl

(以下一部抜粋)

{{- define "gitlab-runner.runner-env-vars" }}  
# some: problem section  
# {{ include "gitlab-runner.gitlabUrl" . }}  
- name: CI_SERVER_URL  
  value: {{ include "gitlab-runner.gitlabUrl" . }}

コメントの some: problem section とその下の {{ include "gitlab-runner.gitlabUrl" . }} のテンプレートを print デバッグしてみます

デバッグ実行

ではデバッグ実行してみます
オプションで --dry-run--debug を使います

  • helm install --dry-run --debug test ./gitlab > debug.log

マニフェストによってはかなり長くなるので結果はファイルなどにリダイレクトしてあげましょう
これで中身を見てみると k8s にデプロイするための定義がつらつらと書かれているのが確認できると思います
その中に以下のようなテンプレートの print デバッグ情報も含まれていると思います

# some: problem section
# "https://gitlab.example.com/"

lint もする

ドライランで実行する前にそもそも構文が間違っていないかチェックすることもできます
手動で print デバッグを入れたりマニフェストを修正した場合には事前に lint しておくと良いと思います

  • helm lint ./gitlab

参考サイト

2021年4月16日金曜日

lego というツールを使うと dns challenge でも Let'sEncrypt の証明書が自動で取得できる

lego というツールを使うと dns challenge でも Let'sEncrypt の証明書が自動で取得できる

概要

Let’sEncrypt で dns challenge を使った場合 TXT レコードの登録が必要になります
DNS サービスに API などがある場合は prehook や posthook を使って自動化することができます
自分で作るのが面倒な場合は golang 製の lego というツールを使うと楽に dns challenge で証明書を取得できることがあります

環境

  • docker 19.03.6
  • lego 4.3.1

コマンド例

  • mkdir lego
docker run --rm \
-e NIFCLOUD_ACCESS_KEY_ID=xxxx \
-e NIFCLOUD_SECRET_ACCESS_KEY=xxxx \
-v $(pwd)/lego:/lego goacme/lego \
--path /lego \
--email your-name@mail.domain \
--dns nifcloud \
--domains *.my-domain.example.com \
--accept-tos \
run

--email, --domains は必須のオプションになります
--accept-tos で確認の入力を省略することができます
path で証明書が保存されるパスを指定できるのでそのパスをホスト側のディレクトリでバインドしてあげましょう
あとはプロバイダに応じた設定を行います

提供されている Provider

かなりたくさんあります
https://github.com/go-acme/lego/tree/master/providers/dns

引数の --dns にプロバイダを指定することができます
route53 や clouddns などのメジャーな DNS サービスがある他さまざまな DNS サービスが対応しているようです
プロバイダによって設定するべき環境変数がことなるので詳細は

  • docker run --rm goacme/lego dnshelp -c route53

などで確認することができます

2021年4月15日木曜日

certbot を docker で使う方法

certbot を docker で使う方法

概要

過去に certbot コマンドを使って Let’sEncrypt で証明書を取得しました
docker を使っても取得できるのでサンプルコマンドを紹介します
なお取得方法は dns challenge 方式で取得しています
ドメイン名やメールアドレスの部分を適宜変更して使ってください

環境

  • docker 19.03.6
  • certbot 1.14.0

取得

  • docker run -it --rm --name certbot -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly --manual --preferred-challenges=dns -d *.example.com -m your-name@mail.domain

一覧表示

  • docker run -it --rm --name certbot -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certificates

失効

  • docker run -it --rm --name certbot -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot revoke --cert-path=/etc/letsencrypt/live/example.com/fullchain.pem

削除

  • docker run -it --rm --name certbot -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot delete -d example.com

2021年4月14日水曜日

macOS で localhost の SOCKS プロキシを構築する

macOS で localhost の SOCKS プロキシを構築する

概要

踏み台となる ssh サーバは各自好きな環境に構築してください
今回はテストなので vagrant で構築しています

踏み台サーバ構築 (vagrant)

  • vagrant init
  • vim Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.network "private_network", ip: "192.168.100.10"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = 4096
    vb.cpus = 2
  end
end
  • vagrant up
  • vagrant ssh

sshd の設定変更

面倒なのでパスワード認証できるようにします

  • sudo passwd vagrant
  • sudo vim /etc/ssh/sshd_config
PasswordAuthentication yes
  • sudo systemctl daemon-reload
  • sudo systemctl restart sshd

SOCKS プロキシの起動

ssh を使うのがてっとり早いです

  • ssh -NTCD 12345 vagrant@192.168.100.10

vagrant 側ではちゃんと ESTABLISHED していれば起動完了です

tcp        0      0 192.168.100.10:22       192.168.100.1:49198     ESTABLISHED

Firefox でプロキシを設定

設定 -> ネットワーク設定
で SOCKS5 プロキシを設定します

  • 手動でプロキシを設定する -> ON
  • SOCKSホスト -> 127.0.0.1
  • ポート -> 12345
  • SOCKS v5 を使用するときは DNS もプロキシを使用する -> ON

動作確認

確認くんなどにアクセスしてプロキシのグローバル IP が表示されることを確認しましょう
今回は同じネットワーク上の VM なので特に変わりません

最後に

クラウドなどに VM がある場合に使う感じになると思います
単純に squid などでもいいと思いますがこちらのほうがアクセス元がわからなくなります

参考サイト

2021年4月13日火曜日

Github + Artifacthub で helm chart を公開する手順まとめ

Github + Artifacthub で helm chart を公開する手順まとめ

概要

自作の helm chart を Github で公開する大まかな流れを紹介します

環境

  • helm 3.5.2

ポイント

  • tgz を作成して http or https で公開すれば OK
  • tgz の作成は helm コマンドを使ってできる

事前準備

すでに helm create test-package で chart は作成している想定です

Github pages の設定

  • main に /docs ディレクトリを作成する
  • Github の設定から Pages を有効にする
    • Settings -> Options -> GitHub Pages

helm repo index

index.yaml を作成します
変更したい箇所があれば手動で変更します

  • helm repo index ../docs --url http://your-name.github.io/test-package

helm package

これで tgz ファイルが作成できます
これを Github Pages で公開します

  • helm package ./test-package

git push

作成された tgz を /docs に移動して Github に push します
これで Github Pages で tgz が公開された状態になります

ArtifactHub でリポジトリの作成

https://artifacthub.io/ にログインしてリポジトリを作成します
URL は Github Pages の URL を記載します

動作確認

  • helm repo add test-package http://your-name.github.io/test-package/
  • helm repo update
  • helm install test-package test-package/test-package

おまけ: README やロゴを設定する方法

  • README.md を tgz ファイルに含めることで自動で展開してくれます
  • ロゴは artifacthub-pkg.yml の logoURL or logoPath を指定すれば自動で設定されます
  • アカウントのロゴは ArtifactHub のプロフィール設定から行えます

参考サイト

2021年4月12日月曜日

k8s ingress-nginx で hostNetwork を使えば 80 or 443 で LISTEN することができる

k8s ingress-nginx で hostNetwork を使えば 80 or 443 で LISTEN することができる

概要

過去 に ingress-nginx を helm を使ってデプロイする方法を紹介しました
hostNetwork についても少し触れていたのですが改めて動作確認してみました
またこのやり方はテスト環境などクラウドロードバランサを用意できない場合に使いましょう
プロダクションなどでは採用しないようが良いです

環境

  • k8s 1.20.1
  • ingress-nginx chart 3.26.0

ingress-nginx controller のデプロイ

オプションで hostNetwork をオンにします
またその際にデプロイするモードを Damonset にする必要があります

  • helm install hostnetwork-test-ingress ingress-nginx/ingress-nginx --set controller.hostNetwork=true --set controller.service.type="" --set controller.kind=DaemonSet

これで各ノードに ingress-nginx controller がデプロイされ各ノードで 80/443 が LISTEN されます

動作確認

適当に Web アプリをデプロイし Ingress を作成して Ingress 経由でアプリにアクセスできるか確認してみましょう

  • helm install request-dumper request-dumper/request-dumper
  • kubectl get svc request-dumper
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE  
request-dumper NodePort 10.104.206.212 <none> 8080:31036/TCP 16m

8080 ポートに Ingress で接続するように Ingress を作成します

  • vim ingress.yml
apiVersion: networking.k8s.io/v1beta1  
kind: Ingress  
metadata:  
  name: hostnetwork-test-ingress  
  annotations:  
    kubernetes.io/ingress.class: "nginx"  
spec:  
  rules:  
    - host: foo.bar.com  
      http:  
        paths:  
          - path: /  
            backend:  
              serviceName: request-dumper  
              servicePort: 8080
  • kubectl apply -f ingress.yml
  • curl -H "Host: [foo.bar.com](http://foo.bar.com/)" 192.168.100.10

こんな感じでノードの 80 番でアクセスできるのが確認できると思います

最後に

あくまでもテストで使うようにしましょう

参考サイト

2021年4月11日日曜日

nginx-ingress-controller でデプロイするノードを固定する方法

nginx-ingress-controller でデプロイするノードを固定する方法

概要

helm を使って k8s/nginx-ingress-controller をデプロイしている場合に nginx の Pod がデプロイされるホストはデフォルトではランダムで決定します
ノードが複数あり Ingress を NodePort で動作させている場合には Ingress がデプロイされるノードによってアクセスする IP が変わるのでデプロイ先を固定にしたほうが扱いやすい場合があります

環境

  • k8s 1.20.4
  • nginx-ingress-controller 3.26.0

nodeSelector を使う

nginx-ingress-controller の values.yml で nodeSelector が指定できるようになっているのでそれを使うのが一番簡単です
helm install や upgrade 時に以下を指定しましょう

--set controller.nodeSelector."kubernetes\.io/hostname"="node1"

gitlab helm chart で指定する場合には

先頭に更に nginx-ingress を付与します

--set nginx-ingress.controller.nodeSelector."kubernetes\.io/hostname"="node1"

参考サイト

2021年4月10日土曜日

k8s nginx-ingress-controller で NodePort 指定時に http と https ポートを指定する方法

k8s nginx-ingress-controller で NodePort 指定時に http と https ポートを指定する方法

概要

nginx-ingress-controller を helm chart で使用する際に http と https のポートを指定する方法を紹介します
また ingress は type: NodePort で動作させる必要があります

環境

  • k8s 1.20.4

ポートを指定する values を set する

以下の 3 つの値をセットしましょう
helm install or upgrade どちらでも使えます

  • --set nginx-ingress.controller.service.type=NodePort
  • --set nginx-ingress.controller.service.nodePorts.http=32080
  • --set nginx-ingress.controller.service.nodePorts.https=32443

NodPort は 30000-32767 を指定しましょう

参考サイト

2021年4月9日金曜日

Gitlab helm chart でデプロイされた minio にログインする方法

Gitlab helm chart でデプロイされた minio にログインする方法

概要

Gitlab 公式の helm chart ではオブジェクトストレージを使った構成を採用しています
デフォルトでは k8s 上に minio をデプロイしそこに git-lfs などのファイルをアップロードしています
今回は minio にアクセスする方法を紹介します
なお namespace は gitlab にデプロイしているのを想定しています

環境

  • k8s 1.20.4
  • Gitlab 13.10.2

アクセス URL の確認

  • kubectl get ingress -n gitlab

これで minio にアクセスするためのホスト情報が確認できます
DNS の設定などは自身で行ってください
IP でアクセスしたい場合は

  • kubectl get pod -n gitlab -o wide

で gitlab-nginx-ingress-controller がデプロイされているノードを確認します
そして

  • kubectl get node -o wide

で対象のノードの IP を確認し

  • kubectl get svc -n gitlab

で NodePort としてバインドされたポートを確認し IP とポートを使ってアクセスしましょう

シークレットの取得

minio にアクセスするとログイン画面が表示されます
そこでアクセスキーとシークレットキーが必要になるので以下のコマンドで取得しましょう

アクセスキー

  • kubectl get secret -n gitlab gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 --decode

シークレットキー

  • kubectl get secret -n gitlab gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 --decode

2021年4月8日木曜日

Gitlab Runner を helm を使って k8s 上にデプロイしてみた

Gitlab Runner を helm を使って k8s 上にデプロイしてみた

概要

過去に Gitlab を helm chart を使って k8s 上にインストールしました
今回は Gitlab Runner のみを k8s 上にデプロイしてみました

環境

  • Gitlab 13.10.2
  • k8s 1.20.4

リポジトリのインストール

  • helm repo add gitlab https://charts.gitlab.io/
  • helm repo search -l gitlab/gitlab

gitlab-runner の chart があることを確認します

Specific runner のデプロイ

プロジェクトの Settings -> CI/CD からトークンを取得します
それを使って helm を実行します

  • helm install --namespace gitlab gitlab-runner gitlab/gitlab-runner --set gitlabUrl=https://gitlab.example.com:32443/ --set privileged=true --set runnerRegistrationToken=xxxxxxxxxxxxxxx

指定するパラメータは

  • gitlabURL
  • privileged (dind を使う場合は必須)
  • runnerRegistrationToken

になります
無事 Pod が動作すると画面からも Runner が登録されているのが確認できます

Shared runner のデプロイ

Shared Runner 用のトークンは Admin Area から取得します
Overview -> Runners にあります

デプロイコマンドは先程と同じです
トークンを取得する場所が異なる点だけ注意しましょう
また helm デプロイ時のリリース名も先程とは別の名前にしましょう

  • helm install --namespace gitlab gitlab-shared-runner gitlab/gitlab-runner --set gitlabUrl=https://gitlab.example.com:32443/ --set privileged=true --set runnerRegistrationToken=xxxxxxxxxxxxxxx

デプロイが完了すると一覧にも表示されるようになります

rbac と runners.config を設定する場合は

Runner が Gitlab からリポジトリを clone する場合に URL がおかしいというエラーが出る場合があります
また serviceAccount が default だと権限がないと言われてエラーになります
その場合は rbac.createrunners.config を設定してあげましょう

helm upgrade --namespace gitlab gitlab-shared-runner gitlab/gitlab-runner --set gitlabUrl=https://gitlab.example.com:32443/ --set privileged=true --set runnerRegistrationToken=xxxxxxxxxxxxxxx --set rbac.create=true --set runners.config="  
[[runners]]  
  clone_url = \"https://gitlab.example.com:32443/\"  
  [runners.kubernetes]  
    image = \"ubuntu:16.04\"  
"

runners.config はヒアドキュメントなので複数行で記載する必要があります

最後に

Gitlab の helm chart をデプロイする際に一緒に Runner もデプロイできるのですが DNS の関係や ACL の関係で一緒にインストールするのが難しい場合は --set gitlab-runner.install=false にして後からインストールしましょう

おまけ: values の取得方法

  • helm inspect values gitlab/gitlab-runner

参考サイト

2021年4月7日水曜日

Gitlab helm chart で gitlab をバージョンアップする方法

Gitlab helm chart で gitlab をバージョンアップする方法

概要

Gitlab helm chart で gitlab のバージョンアップする方法を紹介します

環境

  • Gitlab 13.10.2

やり方

まずはリポジトリを update して最新の helm chart を入手します

  • helm repo update

そして最新の gitlab が取得できているか確認します

  • helm search repo -l gitlab/gitlab | head

あとは upgrade します
global.gitlabVersion を使ってバージョンを指定することでアップグレードできます

例えば --set global.gitlabVersion=13.10.2 を指定して helm upgrade を実行します

ポイント

  • helm install 時に指定した --set がある場合はそれらもすべて指定すること
  • ノードのリソースが足りないと 0/3 nodes are available: 3 Insufficient memory. となりアップデートに失敗する

前者は例えば global.hosts.domain などを指定して helm install した場合は upgrade 時も同じ用に指定しましょう

後者は新バージョンの Pod を先に作成してから古い Pod を削除する流れになるので新バージョンの Gitlab の Pod が動作するリソースが残っていないとエラーになるということです
つまり最低でも 2 つの Gitlab が動作するスペックの k8s クラスタを用意する必要があります

参考サイト

2021年4月6日火曜日

k8s で default の storageClass を作成する方法

k8s で default の storageClass を作成する方法

概要

作成した storageClass はデフォルトでは PersistentVolume で storageName を指定する必要があります
指定なしでも pv を作成する場合は default の storageClassName を作成する必要があります

環境

  • k8s 1.20.4

storageClass の作成

例えば nfs を使った storageClass を作成するには以下の用に作成します
https://hawksnowlog.blogspot.com/2021/03/how-to-use-nfs-as-storageclass-server-on-kubernetes.html

デフォルトにする

上記で作成した nfs の storageClass をデフォルトにするには以下を実行します

  • kubectl patch storageclass nfs -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

動作確認

  • kubectl get storageclasses.storage.k8s.io

default と表示されれば OK です
これで pv 作成時に storageClassName を指定しなくても自動で nfs から pv を作成してくれます

参考サイト

2021年4月5日月曜日

Heroku の Redis Addon が End of Life になったのでアップグレードしてみた

Heroku の Redis Addon が End of Life になったのでアップグレードしてみた

概要

Heroku から連絡があり使っている redis-addon のバージョンが古いからバージョンアップしてくれとの連絡が来ました
なのでアップグレードしてみました

環境

  • macOS 11.2.3
  • heroku 7.51.0
  • redis 4.0.14 -> 6.0

現状の確認

まずは現在使っている redis の情報を確認しましょう
Version が 4.0.14 で End of Life になっているのが確認できます

  • heroku redis:info -a your-app-name
=== redis-silhouetted-79757 (REDIS_URL)
Plan:                   Hobby Dev
Status:                 available
Created:                2019-06-28 03:22 
Version:                4.0.14 (End of Life)
Timeout:                300
Maxmemory:              noeviction
Maintenance:            not required
Maintenance window:     Mondays 20:30 to Tuesdays 00:30 UTC
Persistence:            None
HA Status:              Unavailable
Requires TLS:           No
Keyspace Notifications: Disabled

REDIS_URL の確認

上記の REDIS_URL を確認します
今回は新しい redis にデータを移行する方式を取ります

  • heroku config:get REDIS_URL -a your-app-name

ここで表示される URL はメモしておきましょう

既存の redis のデータを元に新規で redis を作成する

先程確認した REDIS_URL を元に新規で redis を作成します
addons:create--fork オプションを使います

  • heroku addons:create heroku-redis:hobby-dev --fork redis://h:xxxxxxxxx@ec2-xxxxxxxxx:12345 -a your-app-name
Creating heroku-redis:hobby-dev on ⬢ your-app-name... free
Your add-on should be available in a few minutes.
! WARNING: Data stored in hobby plans on Heroku Redis are not persisted.
redis-silhouetted-79757 is being created in the background. The app will restart when complete...
Use heroku addons:info redis-silhouetted-79757 to check creation progress
Use heroku addons:docs heroku-redis to view documentation

作成状況の確認

すぐに新規の redis は払い出されないので状況を逐一確認しましょう
Status: available になれば新規作成+データの移行が完了しています
fork in progress になっている場合はまだデータの移行中になるので古い redis など削除しないようにしましょう

  • heroku redis:info redis-silhouetted-79757 -a your-app-name

アプリが使用する redis を変更する

作成が完了したら使用する redis を変更します
redis:promote を使います
新規で作成された redis を指定しましょう

  • heroku redis:promote redis-amorphous-58530 -a your-app-name

動作確認

アプリにアクセスして正常に動作する確認しましょう

古い redis を削除する

古いバージョンの redis は削除しましょう
addons:destroy で古い redis を指定すれば OK です

  • heroku addons:destroy redis-silhouetted-79757

おまけ: データを移行しないでアップグレードする場合は

いきなり destroy しても良いですが丁寧なのは create -> promote -> destroy かなと思います

  • heroku addons:create heroku-redis:hobby-dev -a your-app-name2
  • heroku redis:promote redis-yyyy-12345 -a your-app-name2
  • heroku addons:destroy redis-xxxxx-12345

参考サイト