【Ansible】コンテナにAnsibleをインストールしたい

 CentOSコンテナにAnsibleをインストールする手順。公式手順だと早々に詰むので(最初のyum installで終わる)、dnfを使ってインストールを行う。


(※)こんなかんじで即詰みする

[root@container /]# yum install ansible
#No match for argument: ansible


 DNFインストールの手順では、EPELリポジトリからインストールするらしい。EPELとはなにかは公式呼んでもよく分からないけれど、雰囲気的には、yumコマンドがパッケージを取りに行く先と似たものが、yum用のものとは別個に存在していて、そこからAnsibleのパッケージを持ってくる……というような感じらしい。
 かつ、DockerHubで配っていたCentOSイメージから作ったコンテナなら、extrasリポジトリにepelのパッケージがあるので、それを読み出すだけでOK。詳しいことはこちらを参照。環境違いの場合のEPELコマンドもここに書いてある。

[root@container /]# dnf install -y epel-release
#Complete!
[root@container /]# dnf install -y ansible
#Complete!

 できたら、Opensshも入れておく。使うかよく分からないけれど、Ansibleと常にセットになっているのできっと使う。ターゲットに接続するときにSSHを使っているのだと思う。たぶん。

[root@container /]# yum install openssh-server
[root@container /]# yum install openssh-clients
#(※)当然ながら、コンテナ内からはGCPのメタデータは見れないので、
#ここから&ここにSSHをつなぎたい場合は手動で鍵を設置する必要がある。

 あとは、Ansbileで使ういつものディレクトリ構造をどっかにつくれば、いつでもAnsibleを叩ける状態になる。

【Jenkins】コンテナにJenkinsをインストールしたい

 公式手順がよくわからないので。CentOSコンテナへのJenkinsインストール手順。


 依存先であるjavaランタイムをインストールする
 JenkinsはJavaが必要なので先に入れておけとのこと(Javaがないと起動できない)らしいので、よくわからないけど、Javaのなんかしらを入れる。
 バージョンを調べるため、yum serach javajava関連のパッケージ一覧を出し、openjdkと書いてあるものうち、良さそうなものを選んでバージョンを選んで番号を控えておく。今回は1.8.0にする。なんで1.8と11の二択になるのかなと思うけど、javaありさえすれば多分何でもいいと思う。

[container /]# yum search java
#java-1.8.0-openjdk.x86_64 : OpenJDK 8 Runtime Environment
#java-1.8.0-openjdk-accessibility.x86_64 : OpenJDK 8 accessibility connector
#java-1.8.0-openjdk-demo.x86_64 : OpenJDK 8 Demos
#java-1.8.0-openjdk-devel.x86_64 : OpenJDK 8 Development Environment
#java-1.8.0-openjdk-headless.x86_64 : OpenJDK 8 Headless Runtime Environment
#java-1.8.0-openjdk-javadoc.noarch : OpenJDK 8 API documentation
#java-1.8.0-openjdk-javadoc-zip.noarch : OpenJDK 8 API documentation compressed #in a single archive
#java-1.8.0-openjdk-src.x86_64 : OpenJDK 8 Source Bundle
#java-11-openjdk.x86_64 : OpenJDK 11 Runtime Environment
#java-11-openjdk-demo.x86_64 : OpenJDK 11 Demos
#java-11-openjdk-devel.x86_64 : OpenJDK 11 Development Environment
#java-11-openjdk-headless.x86_64 : OpenJDK 11 Headless Runtime Environment
#java-11-openjdk-javadoc.x86_64 : OpenJDK 11 API documentation
#java-11-openjdk-javadoc-zip.x86_64 : OpenJDK 11 API documentation compressed in#a single archive
#java-11-openjdk-jmods.x86_64 : JMods for OpenJDK 11
#java-11-openjdk-src.x86_64 : OpenJDK 11 Source Bundle
#3java-11-openjdk-static-libs.x86_64 : OpenJDK 11 libraries for static linking
[container /]# yum install java-1.8.0-openjdk
#Complete!

 Jenkinsインストールは、リポジトリのコピー・認証鍵作成(いるのかな?)・インストールの順で実施できる。

#リポジトリのコピー
[container /]# curl -o /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

#認証鍵のコピー
[container /]# rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

#インストール
[container /]# yum -y install jenkins
#Complete!

#自動起動の有効かおよびサービス起動
[container /]# systemctl enable jenkins
[container /]# systemctl start jenkins

 リッスンポートの変更
 Jenkinsはデフォルトで8080ポートを使用しているので、必要に応じてこれを変更する(この環境では、Docker母機の8083番からコンテナの80番へポートフォワーディングしているため、リッスンポートを80番へ変更)
 ちなみにHTTPS PORT云々という設定項目を構うと死ぬので、HTTPS化しないなら注意。するなら証明書をつくったりいろいろ追加手順があるらしい。知らないけど

[container /]# cat /etc/sysconfig/jenkins | grep 8080
## Default:     8080
JENKINS_PORT="8080" #←デフォルトで8080ポートになっているのでこれを変更

[container /]# # systemctl reload jenkins

 ここまできたら、WebGUIへ移動する。母機のIP+ポート番号でアクセスすると、Jenkinsの
(ちなみにここで「アクセスが拒否されました」と出て、かつFWやiptableに何の問題もないときは、Jenkinsの再インストールで解決する。理由は謎)

f:id:makitoriel:20210504160801p:plain


 初期パスワードは下記のファイルに書いてある。

[container /]# cat /var/lib/jenkins/secrets/initialAdminPassword


 この先は、案内に従って適当にいれていけばOK! Jenkins is readyが出れば、使用可能になる。

【Docker】コンテナをsystemctlがつかえる形で起動する

まとめ
コンテナでsystem controlを使いたい場合は、起動時にsytem controlにPIDの1番が振られるように工夫が必要である

 作成したコンテナにパッケージをインストールして、システムコントロールで起動しようとした際に(OS:CentOS)、以下のようなエラーで弾かれる。

[container]# systemctl
#   System has not been booted with systemd as init system (PID 1). Can't operate.
#  Failed to connect to bus: Host is down

 システムコントロールはPID1番が割り振られていてはじめてinitとして機能するが(参考)、Dockerがコンテナを起動した際にシステムコントロールにPIDの1番が振られるような起動の仕方をしないため、システムコントロールが動けなくなっている。


 であれば、コンテナ起動時にシステムコントロールのPIDが1になるように指定してあげればいい。docker runの使い方を見ていると、イメージ名のあとに、コンテナの箱をつくった直後に実行するコマンドを指定できるとのこと。

使い方: docker run [オプション] イメージ [コマンド] [引数...]
(……)
docker run コマンドは、まず指定されたイメージ上に書き込み可能なコンテナ・レイヤを create (作成)します。それから、指定されたコマンドを使って start (開始)します。

 
 なのでここにinitがシステムコントロールになるように指定して起動してみる。イメージ(centos)の後にある\sbin\initがそれにあたる。

[makitori@instance ~]# sudo docker run -it --name container centos \sbin\init

 これで起動したコンテナでシステムコントロールを呼ぶと、エラー無く実行してくれる。

[makitori@instance ~]# sudo docker exec container bash
[container]# systemctl start httpd
[container]#

【Linux】コマンドラインを受けたい

 Linuxにおいたプログラムでコマンドラインから引数を受ける方法
 
 実行ファイルを指定して実行する際に勝手に引数を渡しても、引数が多すぎるなどのエラーは起こらない。引数を受けるプログラム側で受け皿を用意すれば、引き取ることができる。
 argc(argument count)が引数の個数を、argv(argument vector)が引数が実際に格納された配列を指し、そこへのポインタを渡してあげることで、プログラムから引数を参照できるようになる。
 なおargvのひとつめ(インデックスでいうと0)にはプログラム名が入っているので(例外はある)、引数が格納されるのはふたつめから。第一引数がインデックス1に、第二引数がインデックス2に入るかんじ。


 

#chek_cl_args

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
        int i;
        printf("argc=%d\n", argc);
        
        for (i=0; i<argc; i++){
                printf("argv[%d]=%s\n",i,argv[i]);
        }
        exit(0);

 これをビルドして実行してみると、argcで引数の個数を、argvで実際の引数をリストで受けていることを確認することができる。

[makitori@instance ckeck_cl_args]$ gcc -o check_cl_args check_cl_args.c
[makitori@instance ckeck_cl_args]$ ./check_cl_args arg1 arg2 arg3
#argc=4
#argv[0]=./check_cl_args
#argv[1]=arg1
#argv[2]=arg2
#argv[3]=arg3

 

【Linux】C言語によるプログラミングの環境を用意したい

 まずはプログラミング環境が整っていることの確認。
 C言語で書くので、gccおよびviがインストールされていること。

[makitori@instance ~]$ gcc -dumpversion
#4.8.5
[makitori@instance ~]$ vi -version
#VIM - Vi IMproved
#version 7.4.629

 両方入ってる!
 GCPで作成したCentOSVMには、これらのパッケージは最初からインストールしてくれている模様。うれしい(覚えてないだけで、もしかしたら自分で入れたかもしれないけど)。


 次に、ハローワールドをやってみる。

 任意の場所で拡張子.cのファイルを作成し、そのファイルをgccでビルド(コンピュータが実行可能なかたちになおす)する。
 コンパイルのコマンドはggc-o<コンパイル後のファイル名>コンパイルするファイル名で、-oオプションはコンパイル後の実行ファイルの名前を指定するオプション。

[makitori@instance ~] mkdir hello && cd hello
[makitori@instance hello] vi hello.c
[makitori@instance hello] gcc -o hello hello.c
[makitori@instance hello] ./hello
#HelloWorld


 viの中身はこんなかんじの、あっちこっちで何度も書いたハローワールド。

# include <stdio.h>

int main(){
    printf(“HelloWorkd\n”);
    return 0;
}


 はじめのいっぽでした

【Docker】コンテナをつくりたい

 dockerdが動いている環境での、コンテナの作り方。
 イメージ(コンテナの設計図)をDockerHubからプルしてきて、そのイメージを指定して起動するだけなので2コマンド。

[makitori@instance ~]$ sudo docker pull centos
[makitori@instance ~]$ sudo docker run -it --name container centos
[root@1e466ab28f3a /]#

 runのときに指定したコマンドオプションは、-iが「コンテナの標準入力に接続する(interface)」、-tが「疑似ターミナル割り当て(tty)」を意味し、-itの指定で、コンテナをコマンド操作することができるようになる。


 この先は、サーバの初期設定と同じ(yumをアップデートして、必要なパッケージを入れて、……)
 ただ、セキュリティは母体となるサーバで担保しているとして、rootログインのままそのまま使ってOKみたい。しらないけど。

【GCP/Linux】telnetをセットアップしたい

 telnet接続のテストのために、telnetサーバーを設定したい。接続される側がtelnetサーバ、接続する側がtelnetクライアント。GCPで起動したCentOSインスタンスtelnetクライアントはデフォルトで使えるようになっているので、接続される側にtelnetを入れて、あとFWの穴あけをすればOK!

Server側(Telnet接続をされる側)

# telnetクライアントおよびtelnetサーバの確認
[makitori@instance-target ~]# yum list installed | grep telnet

# telnetクライアントおよびtelnetサーバのインストール
[makitori@instance-target ~]# yum -y install telnet telnet-server

# 自動起動の有効化
[makitori@instance-target ~]# systemctl enable telnet.socket

# 自動起動の確認
[makitori@instance-target ~]# systemctl list-unit-files | grep telnet.socket
#telnet.socket                               enabled

# telnet起動
[makitori@instance-target ~]# systemctl start telnet.socket

 FWは、GOC側で23番ポートを開放。tenletはあんまりセキュアではない(はず?)なので、接続元・接続先を絞って最低限の穴あけとする、かつ記録ありとして、使い終わったらallowルールを無効化して閉じておく。
f:id:makitoriel:20210418000238p:plain