togatttiのエンジニアメモ

過度な期待はしないでください.

Jenkinsを2系から、1系に応急的に切り戻す

バージョンが1.6系の古のJenkinsを運用していたが、誤ってapt upgradeしてしまいバージョンが 2.1系にあがり、起動しなくなってしまった。

OSは、Ubuntu 14.04。

# apt upgradeの抜粋
Unpacking jenkins (2.179) over (1.6xx)

切り戻しをしたので、メモしておく。

ただし、応急療法なので、動作性の責任は取れない。。

結論からいうと、以下の二つの対応で、切り戻しができた。

  • jenkins.warの差し替え
  • /etc/init.d/jenkinsの修正

jenkins.warの差し替え

/usr/share/jenkins配下に、2系のjenkins.warがあるので、それを元々運用していたバージョンに差し替える。

# cd /usr/share/jenkins
# mv jenkins.war jenkins.war.20190527a
# wget https://updates.jenkins-ci.org/download/war/1.6xx/jenkins.war

/etc/init.d/jenkinsの修正

修正しないと、以下のように起動スクリプトJavaのバージョン判定に引っかかり、起動できない。

# service jenkins status
Found an incorrect Java version
Java version found:
java version "1.7.0_201"
OpenJDK Runtime Environment (IcedTea 2.6.17) (7u211-2.6.17-0ubuntu0.1)
OpenJDK 64-Bit Server VM (build 24.201-b00, mixed mode)

Aborting

なので、バージョンを判定する箇所をコメントアウトする。

# diff -u /etc/init.d/jenkins.20190527a /etc/init.d/jenkins
--- /etc/init.d/jenkins.20190527a 2019-05-27 18:20:38.400852420 +0900
+++ /etc/init.d/jenkins       2019-05-27 18:16:02.159208259 +0900
@@ -59,15 +59,15 @@
 # Work out the JAVA version we are working with:
 JAVA_VERSION=$($JAVA -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*".*/\1\2/p;')

-if [[ ${JAVA_ALLOWED_VERSIONS[*]} =~ "$JAVA_VERSION" ]]; then
-    echo "Correct java version found" >&2
-else
-    echo "Found an incorrect Java version" >&2
-    echo "Java version found:" >&2
-    echo $($JAVA -version) >&2
-    echo "Aborting" >&2
-    exit 1
-fi
+#if [[ ${JAVA_ALLOWED_VERSIONS[*]} =~ "$JAVA_VERSION" ]]; then
+#    echo "Correct java version found" >&2
+#else
+#    echo "Found an incorrect Java version" >&2
+#    echo "Java version found:" >&2
+#    echo $($JAVA -version) >&2
+#    echo "Aborting" >&2
+#    exit 1
+#fi

 # load environments
 if [ -r /etc/default/locale ]; then

正常に起動することを確認する。

# service jenkins start
 * Starting Jenkins Automation Server jenkins
   ...done.
# service jenkins status
Jenkins Automation Server is running with the pid 26347

AWS 認定ソリューションアーキテクトを受けてきた

結論

先月の終わりに、AWS 認定ソリューションアーキテクト - アソシエイトを受けて、合格した。

www.certmetrics.com

スペック

勉強期間

2週間。

勉強方法

www.udemy.com

をやりながら、AWSコンソールの操作、基本的なサービスを覚えた。

aws.amazon.com

ブラックベルトを一通り読んだ。

aws.koiwaclub.com

有料プランを申し込んで、全ての問題を解いた。

www.amazon.co.jp

これも2周くらい読み込んだ。

終わってみて

aws.amazon.com

AWSに関する基本知識が身につき、ケーススタディに書いてある各社のシステム構成図が読めるようになった。

自分も設計できる機会があればいいな。

次は、AWS 認定ソリューションアーキテクト - プロフェッショナルを目指したい。

Container Linuxにkubeadmを入れて、k8sクラスタを構築する

はじめに、Container Linuxを3台用意しておく。

  • k8s01(192.168.0.2/24)
  • k8s02(192.168.0.3/24)
  • k8s03(192.168.0.4/24)

バージョンは、こちら。

$ grep VERSION= /etc/os-release
VERSION=2023.5.0

Container Linuxの初期設定

各ホストで、パスワード、ホスト、固定IPアドレスの設定を済ませる。

パスワードの設定
$ sudo passwd core
ホストの名前設定
$ sudo hostnamectl set-hostname k8s01
$ sudo vi /etc/hosts
$ grep k8s01 /etc/hosts
127.0.0.1       localhost k8s01
固定IPアドレスの設定
### k8s01の設定
$ sudo vi /etc/systemd/network/static.network
$ sudo cat /etc/systemd/network/static.network
[Match]
Name=eth0

[Network]
Address=192.168.0.2/24
Gateway=192.168.0.1
DNS=8.8.8.8

### ネットワークの再起動
$ sudo systemctl restart systemd-networkd

kubeadmのインストール

kubeadmのインストール - Kubernetes

にあるContainer Linuxのインストール手順をrootで実行する。

$ cat install.sh
### CNIをインストール
CNI_VERSION="v0.6.0"
mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-amd64-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz
### CRICTLをインストール
CRICTL_VERSION="v1.11.1"
mkdir -p /opt/bin
curl -L "https://github.com/kubernetes-incubator/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz" | tar -C /opt/bin -xz
### kubeadm, kubelet, kubectlをインストール
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
mkdir -p /opt/bin
cd /opt/bin
curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/amd64/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}
curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/kubelet.service" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service
mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/10-kubeadm.conf" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
### kubeletを有効にする。
systemctl enable kubelet && systemctl start kubelet
$ sudo sh install.sh

k8sクラスタ構築

マスターノード構築
### k8s01側
### クラスタの初期化
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
### ブリッジのパケットをiptablesで処理できるようにする設定
$ sudo sysctl net.bridge.bridge-nf-call-iptables=1
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
### masterとして稼働していることを確認
$ kubectl cluster-info
Kubernetes master is running at https://10.200.8.117:6443
KubeDNS is running at https://10.200.8.117:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
### クラスタに参加するためのkubeadm join コマンドが発行されるので、控えておく。
ノード追加
### k8s02とk8s03側
$ sudo kubeadm join 192.168.0.2:6443 --token pu2npf.e42wltclx0f64bdc --discovery-token-ca-cert-hash sha256:9eb6af07398ebf79ef0acb0b70e18fca5f26c00912c2e132bbe634568316c347
クラスタ確認
### k8s01側
$ kubectl get nodes
NAME    STATUS     ROLES    AGE   VERSION
k8s01   NotReady   master   1m   v1.13.4
k8s02   NotReady   <none>   3s   v1.13.4
k8s03   NotReady   <none>   3s    v1.13.4
Flannel設定

クラスタが構築できたが、STATUSがNotReadyになっている。

ノードをまたいで、Pod同士が通信できるように、Flannelで、オーバレイネットワークを設定する。

### k8s01側
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
$ kubectl get nodes
NAME    STATUS   ROLES    AGE     VERSION
k8s01   Ready    master   5m28s   v1.13.4
k8s02   Ready    <none>   3m49s   v1.13.4
k8s03   Ready    <none>   2m23s   v1.13.4

以上で、kubeadmを用いてk8sクラスタを構築することができた。

参考

https://coreos.com/flannel/docs/latest/kubernetes.html

kubeadmを使用したシングルマスタークラスターの作成 - Kubernetes

http://sysy.livedoor.biz/archives/9791596.html

psqlで、冗長な箇所を省き結果を取得する

例えば、PostgreSQLのpg_hba.confのパスだけをpsqlで取りたいとき、

単純に、-cオプションを使うと、

$ psql -c 'SHOW hba_file'
              hba_file
-------------------------------------
 /etc/postgresql/10/main/pg_hba.conf
(1 row)

余分な箇所が混ざる。

その場合、-A -tオプションを追加すると冗長な部分を排除し期待していた結果が取得できる。

$ psql -At -c 'SHOW hba_file'
/etc/postgresql/10/main/pg_hba.conf

今までは、こんな形でシェル芸してた。

$ psql -c 'SHOW hba_file' | grep /etc | sed -e 's/ //'
/etc/postgresql/10/main/pg_hba.conf

SSHでアクセスできるEC2インスタンスを構築する

docs.aws.amazon.com

VPCの理解を深めたいと思い、上記のガイドを読みながら、SSHでアクセスできる EC2インスタンスをTerraformで作成した時の雑記です。

SSHでインターネット経由でつなげられるEC2インスタンスを構築するためには、EC2インスタンス以外に、 VPCゲートウェイ、ルーティングテーブル、セキュリティグループの設定が必要になるので作成していく。

Terraformのインストール

手元のUbuntu 18.04に、Terraformをインストールする。

# cd /usr/local/src
# wget https://releases.hashicorp.com/terraform/0.11.11/terraform_0.11.11_linux_amd64.zip
--2019-02-26 11:41:14--  https://releases.hashicorp.com/terraform/0.11.11/terraform_0.11.11_linux_amd64.zip
Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.1.183, 151.101.65.183, 151.101.129.183, ...
Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.1.183|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 20971661 (20M) [application/zip]
Saving to: ‘terraform_0.11.11_linux_amd64.zip’

terraform_0.11.11_linu 100%[==========================>]  20.00M  33.3MB/s    in 0.6s

2019-02-26 11:41:15 (33.3 MB/s) - ‘terraform_0.11.11_linux_amd64.zip’ saved [20971661/20971661]

# unzip terraform_0.11.11_linux_amd64.zip
Archive:  terraform_0.11.11_linux_amd64.zip
  inflating: terraform
# cp -p terraform /usr/local/bin/
# terraform version
Terraform v0.11.11

tfファイルの作成

次に、作業ディレクトリに、SSHの鍵ペアを作成する。

# su togattti
$ mkdir ~/sagyou
$ cd ~/sagyou/
$ ssh-keygen -t rsa -f id_rsa_ec2

terraform.tfvarsを作成して、変数を定義する。

aws_access_key = "xxxxxx"
aws_secret_key = "xxxxxx"
aws_region = "ap-northeast-1"
key_name = "id_rsa_ec2"
public_key = "id_rsa_ec2.pub"

ec2.tfというファイルを作成して、設定を入れる。

まず、variableを記載する。 これで、${var.aws_access_key}のtfファイルの中では、変数を通して値を参照できる。

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "aws_region" {}
variable "key_name" {}
variable "public_key" {}

AWSを使う際の初期設定を書く。

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "${var.aws_region}"
}

VPCを作成する。この中にサブネットを切り、その中でEC2インスタンスを起動する。

resource "aws_vpc" "my-vpc" {
    cidr_block = "10.0.0.0/16"
    enable_dns_hostnames = true
    enable_dns_support = true
    tags {
        Name = "my-vpc"
    }
}

VPCの中に、サブネットを作成する。

このサブネット内でEC2インスタンスを起動させる。

resource "aws_subnet" "my-subnet" {
    # cidrsubnetで計算すると10.0.32.0/19になる。
    cidr_block = "${cidrsubnet(aws_vpc.my-vpc.cidr_block, 3, 1)}"
    vpc_id = "${aws_vpc.my-vpc.id}"
    availability_zone = "ap-northeast-1a"
}

ElasticIP(固定のIPアドレス)をインスタンスに付与する。

resource "aws_eip" "my-eip" {
    instance = "${aws_instance.my-ec2.id}"
    vpc = true
}

インターネットに出るためのゲートウェイを設定する。

resource "aws_internet_gateway" "my-gw" {
    vpc_id = "${aws_vpc.my-vpc.id}"
    tags {
        Name = "my-gw"
    }
}

インスタンスからゲートウェイまでのルーティングテーブルを設定する。

resource "aws_route_table" "my-route-table" {
    vpc_id = "${aws_vpc.my-vpc.id}"
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.my-gw.id}"
    }
    tags {
        Name = "my-route-table"
    }
}

サブネットとルーティングテーブルを関連づける。

resource "aws_route_table_association" "subnet-association" {
    subnet_id = "${aws_subnet.my-subnet.id}"
    route_table_id = "${aws_route_table.my-route-table.id}"
}

ここまでで、VPCの設定が完了。

次にセキュリティグループの設定。

ingress(インターネットからインスタンスへの入りの通信)で、SSHを許可する。

resource "aws_security_group" "my-security-group" {
    name = "allow-ssh"
    vpc_id = "${aws_vpc.my-vpc.id}"
    description = "Allow SSH port"

    # inbound traffic to a instance
    ingress {
        cidr_blocks = ["0.0.0.0/0"]
        from_port = 22
        to_port = 22
        protocol = "tcp"
    }

    # outbound traffic from a instance
    egress {
        from_port = 0
        to_port = 0
        protocol = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

SSHで使用する鍵ペアを設定する。

resource "aws_key_pair" "my-key-pair" {
    key_name = "${var.key_name}"
    public_key = "${file(var.public_key)}"
}

Amazon LinuxのEC2インスタンスを作成する。

resource "aws_instance" "my-ec2" {
    ami = "ami-0148288598227344a"
    instance_type = "t2.micro"
    monitoring = true
    tags {
        Name = "my-ec2"
    }
    key_name = "${var.key_name}"
    vpc_security_group_ids = ["${aws_security_group.my-security-group.id}"]
    subnet_id = "${aws_subnet.my-subnet.id}"

構築が完了したら、Elastic IPを出力する。

output "EIP for EC2 instance" {
    value = "${aws_eip.my-eip.public_ip}"
}

Terraform初期化、実行

まず、terraform initで初期化。

$ terraform init

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 1.60"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

terraform applyで、インスタンス構築。

$ terraform apply
(snip)

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

EIP for EC2 instance = 192.168.0.3

構築が完了したら、SSHしてみる。 IPは、ダミー。

$ ssh -i id_rsa_ec2 ec2-user@192.168.0.3 'hostname'
  ip-192-168-0-3.ap-northeast-1.compute.internal

作成tfファイルなどは、以下のリポジトリにおいた。

github.com

参考

Setting Up an AWS EC2 instance with SSH access using Terraform