/

ICTSC2020 本選にご参加いただいた学生の皆様、お疲れ様でした。

今回のICTSC2020を以ってICTSCは活動休止となり、学生の皆様は非常に驚かれたと思います。我々運営としても、こういった活動の場が無くなってしまうのは非常に寂しいですが、ここで培った知識・技術を今後に活かしていただければと思います。

今回出題した問題の問題文、及び問題解説を公開します。
ぜひ今後の研鑽にご利用いただければと思います。

Container

なぜか動きません!

docker-mailman

いつの間にか復活している君

コンテナに繋がらない

DNS

名前解決ができなくなった?

Webサーバーに繋がらない!

DNSサーバを作りたかったらしい

FTP

FTPなんもわからん

FTPが壊れちゃった!

k8s

Nginxが展開できない

証明書の取得ができない!!

Linux

このOpenstackなんか変だよぉ…

続・このOpenstackなんか変だよぉ…

まだだ、まだ終わらんよ

部署を統合したが…

LoadBalancer

リバースプロキシが動かない

Program

何かがおかしい。。。。

ボク わるいフレームワークじゃないよ

Routing

インターネット壊れた

あれ、おかしい。。。。

Tunnel

とんとんとんねる

GREが繋がらない!

Web

Server Sent Eventsが動作しない‼

 /
カテゴリー

はじめに  

作問者のabeです. 実はこの問題は史実に基づいて作られた問題です.

回答を見ていると私と同じ罠に引っかかったチームが居て嬉しかったです(?).

問題文  

部長さんへ

新米エンジニアの捕鯨太郎です。 プロジェクトでWEBサーバを構築するとのことなので、 docker-composeを使用してWEBサーバを構築しました。 無事に起動し、WEBページも確認できたのですが、 再起動するとアクセスできなくなってしまいました。

自動的に再起動するように記述してあるので不可解です。 しかも、トラブルシュートしているといつの間にか アクセスできるようになります。自分には原因がわかりません。

お知恵を拝借したいのですが、 お時間をいただけないでしょうか。

前提条件  

  • ~/web-server/docker-compose.ymlがあり編集可能
  • docker ps -aなどで確認するとコンテナが起動している

初期状態  

踏み台から $ curl 192.168.17.1 をしても応答がない

終了状態  

再起動しても踏み台から $ curl -I 192.168.17.1 をするとステータスコード200のレスポンスが返ってくる

答え  

まずは初期状態を確認しましょう.

~ curl 192.168.17.1
curl: (7) Failed to connect to 192.168.17.1 port 80: Connection refused

WEBページにアクセスできないのが確認できます. 次にコンテナの様子をみてみましょう.

user@docker:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS                NAMES
4e7db3e7cc97        nginx:latest        "/docker-entrypoint.…"   3 minutes ago       Up Less than a second   0.0.0.0:80->80/tcp   web-server_nginx_1

あれあれ,起動しているな…

もう一度確認すると… いつの間にか復活してる!!!

~ curl 192.168.17.1 -I
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Sun, 07 Mar 2021 03:33:11 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 15 Dec 2020 13:59:38 GMT
Connection: keep-alive
ETag: "5fd8c14a-264"
Accept-Ranges: bytes

確認作業を行っているうちに復活してしまいました.

実はdockerコマンドを叩くとデーモンが起動するという罠があります.先ほどのdocker ps -aを見てみるとUp Less than a secondとあり,起動したてなのがわかります.

以下のコマンドで確認するとデーモンは起動していますが,enableになっていない事がわかります.

ictsc@docker:~$ systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-03-07 12:32:53 JST; 9min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 2176 (dockerd)
      Tasks: 17
     Memory: 114.7M
     CGroup: /system.slice/docker.service
             ├─2176 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
             └─2362 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.18.0.2 -container-port 80
             

ictsc@docker:~$ systemctl is-enabled docker
disabled

そう,enableのし忘れですね.以下のコマンドで解決です.

systemctl enable docker

採点基準  

dockerサービスをenableできたか.

おわりに  

前提条件に書いた2点,docker-compose.ymlが編集可能である,docker ps -aすると起動している, に引っかかってくれたチームがいて嬉しかったです.

冷静に確認されると一瞬で解決してしまう問題なので簡単枠で出題しました.

 /
カテゴリー

はじめに  

作問者のabeです. この問題は昔バックアップパーティションに救われた経験から作りました.

概要  

ベテランエンジニアの虎魂くんはWEBサーバの運用を行っていました. ある日,記憶から消えかけていたような昔のプロジェクトのお客さんから電話がありました.

どうやらWEBサーバにアクセスするとエラーページが表示されるようです. 原因の理由と解決方法を回答してください.

前提条件  

  • WEBページのデータのバックアップはない.
  • WEBページの公開パスなどの変更は可能.

初期状態  

手元のPCから $ curl 192.168.11.1 をしてもエラーコードが帰ってくる.

終了状態  

  • 障害前に表示されていたページが表示されること.
  • 手元のPCから $ curl 192.168.11.1 をするとステータスコード200のレスポンスが返ってくる.

採点基準  

  • /dev/sdbのパーティションが壊れていることに気が付く 30%
  • 障害前のWEBページが確認できる 70%

答え  

まずは終了状態の確認を行います.400番台なのでエラーが発生しています.

ictsc@web:~$ curl localhost
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>

一応Nginxが起動しているか確認します.起動しています.

ictsc@web:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-03-07 13:31:36 JST; 27min ago
       Docs: man:nginx(8)
   Main PID: 585 (nginx)
      Tasks: 2 (limit: 1168)
     Memory: 11.5M
     CGroup: /system.slice/nginx.service
             ├─585 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             └─586 nginx: worker process

Warning: some journal files were not opened due to insufficient permissions.

/var/log/nginx/error.logを確認すると以下のエラーが出力されています.

2021/03/07 13:55:27 [error] 586#586: *1 directory index of "/mnt/data/" is forbidden, client: 127.0.0.1, server: _, request: "GET / HTTP/1.1", host: "localhost"

ls /mnt/data/で確認するとディレクトリが空なのがわかります. ここでパスを見てみるとmntである事がわかります. mntディレクトリはファイルシステムをマウントする用途に使われるので/etc/fstabを確認します.

以下のようなマウントポイントが設定されてました.

/dev/sdb1 /mnt/data ext4 defaults 0 0

対象のデバイスを確認します.

sudo gdisk /dev/sdb 

するとエラーメッセージが出力されます.抜粋した以下を確認するとメインのパーティションテーブルが壊れている事がわかります. しかし,バックアップは生きているようなので復旧していきます.

Main header: ERROR
Backup header: OK
Main partition table: ERROR
Backup partition table: OK

復旧するので1番を選択

Found invalid MBR and corrupt GPT. What do you want to do? (Using the
GPT MAY permit recovery of GPT data.)
 1 - Use current GPT
 2 - Create blank GPT

Your answer: 1

リカバリモードに入り,バックアップから復元し書き込みます.

Command (? for help): r

Recovery/transformation command (? for help): c
Warning! This will probably do weird things if you've converted an MBR to
GPT form and haven't yet saved the GPT! Proceed? (Y/N): y

Recovery/transformation command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdb.
The operation has completed successfully.

マウントしてみます.

sudo mount -a

確認すると正常に復旧できた事がわかります.

ictsc@web:~$ cat /mnt/data/index.html 
<!DOCTYPE html>
<html lang="ja">
        <head>
                <meta charset="utf-8" />
                <link rel="stylesheet"  href="style.css">
                <title>タイトル</title>
                <script
                          src="https://code.jquery.com/jquery-3.3.1.min.js"
                            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
                              crossorigin="anonymous"></script>
        </head>
        <body>
                <main>
                        <p>ICTSC WEB!!!</p>
                </main>
        <script>
                $(function(){
                });
        </script>
        </body>
</html>

おわりに  

この問題は物理ディスクを2つ使うため,自分たちで仮想基盤を運用する本戦で出そうと思ってました. 150点問題としては多くのチームに解いていただけたので嬉しかったです.

gdiskではなくtestdiskを用いて回答していたチームもいました. どちらを使用しても終了条件を満たせるので満点にしています.

来年から社会人なので,最後の作問でしたが楽しかったです.

 /
カテゴリー

問題文

概要

k8sクラスターにcert-managerをインストールしhttp01認証で証明書を発行するissuerを設定した。
その上でhostのnginxのpodを展開するDeploymentと、それを公開するService、Ingressを記述した/home/user/manifests/web.yamlを作成しapplyした。
しかし、なぜか証明書が発行されない。その理由と解決方法を報告してほしい。

トポロジを以下の図で示す。

前提条件

  • cert-managerで取得する証明書は自己署名証明書を使用している
    • hostcert-managerなど必要なものにはルートCA証明書をインストール済み
  • hostuserユーザーでkubectlコマンドが利用できる
  • host/home/user/manifestsに今回applyしたmanifestが保存されている
    • cert-manager.yaml ingress-controller.yaml root-ca.yaml変更しないこと
    • web.yamlの再展開(kubectl delete, kubectl applyなど)可
  • acme-serverには、追加でDNSサーバーが稼働しており以下のレコードが設定されている
        IN      NS      ictsc.test.
        IN      A       192.168.20.125

ca      IN      A       192.168.20.125
www     IN      A       192.168.20.1
  • lbにはkeepalivedがインストールされている。
    • 変更しないこと

初期状態

  • hostcurl -L www.ictsc.testを実行したとき以下のようなエラーになる
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
  • hostkubectl get certを実行したときwww-ictsc-test-tlsのREADYがFalseになっている

終了状態

  • hostcurl -L www.ictsc.testを実行したときにnginxの初期ページが表示される
    • 証明書が設定されている
  • hostkubectl get certを実行したときにwww-ictsc-test-tlsのREADYがTrueになっている

接続情報

lbhostのみSSHログインできる。

VM名ホスト名ユーザパスワード
lb192.168.20.1userictsc2020
host192.168.20.20userictsc2020
acme-server192.168.20.125
k8s-master192.168.20.129
k8s-worker1192.168.20.130
k8s-worker2192.168.20.131

解説

原因

cert-managerはhttp01認証を行うときにacme challengeが行えるかセルフチェックを行います。その際、www.ictsc.testつまり192.168.20.1宛てにGETリクエストを行いますが、このリクエストの戻りのパケットがnginxのPODから直接cert-managerのPODに送られてしまいます。
その時の送信元アドレスが、リクエストの送信時の宛先と異なるためセルフチェックのリクエストは失敗してしまい証明書の取得が行われませんでした。

以下のようにセルフチェックが失敗していることを確認できます。

user@host:~$ kubectl describe challenges.acme.cert-manager.io
Name:         www-ictsc-test-tls-dhksj-696946275-1037365539
Namespace:    default
Labels:       <none&gt;
Annotations:  <none&gt;
API Version:  acme.cert-manager.io/v1
Kind:         Challenge
...
省略
...
Status:
  Presented:   true
  Processing:  true
  Reason:      Waiting for HTTP-01 challenge propagation: failed to perform self check GET request 'http://www.ictsc.test/.well-known/acme-challenge/c4mi9je6PJ87H9ulTtAPOu1xSjXEyDo9': Get "http://www.ictsc.test/.well-known/acme-challenge/c4mi9je6PJ87H9ulTtAPOu1xSjXEyDo9": dial tcp 192.168.20.1:80: connect: connection timed out
  State:       pending
...
省略
...

解決策

解決策としては以下のことが考えられます。

  • LBにhaproxyやnginxなどのリバースプロキシを用いる
  • LBにヘアピンNATの設定を行う

今回は、keepalivedを変更できないのでヘアピンNATの設定を行います。

/etc/sysctl.confに以下の設定を追記し更新します。

$ sudo vim /etc/sysctl.conf
net.ipv4.vs.conntrack=1 # 最終行に追記

$ sudo sysctl -p

iptablesで内部からの通信をMASQUERADEする設定を行い永続化します。

$ sudo iptables -t nat -A POSTROUTING -s 192.168.20.128/25 -m ipvs --vaddr 192.168.20.1/32 -j MASQUERADE
$ sudo netfilter-persistent save

/home/user/manifests/web.yamlをapplyし直すとkubectl get certでREADYがTrueになることを確認できます。
またcurl -L www.ictsc.testで正常にnginxのページが表示されます。

user@host:~/manifests$ kubectl delete -f web.yaml
deployment.apps "web" deleted
service "web" deleted
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions "a-web" deleted

user@host:~/manifests$ kubectl apply -f web.yaml
deployment.apps/web created
service/web created
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/a-web created

user@host:~/manifests$ kubectl get cert
NAME                 READY   SECRET               AGE
www-ictsc-test-tls   True    www-ictsc-test-tls   35s

user@host:~/manifests$ curl -L www.ictsc.test
<!DOCTYPE html&gt;
<html&gt;
<head&gt;
<title&gt;Welcome to nginx!</title&gt;
<style&gt;
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style&gt;
</head&gt;
<body&gt;
<h1&gt;Welcome to nginx!</h1&gt;
<p&gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p&gt;

<p&gt;For online documentation and support please refer to
<a href="http://nginx.org/"&gt;nginx.org</a&gt;.<br/&gt;
Commercial support is available at
<a href="http://nginx.com/"&gt;nginx.com</a&gt;.</p&gt;

<p&gt;<em&gt;Thank you for using nginx.</em&gt;</p&gt;
</body&gt;
</html&gt;

採点基準

  • 理由が説明できている 20%
  • 解決方法が記述されておりその解決方法で解決が可能 80%

さいごに

問題を解いていただきありがとうございました。

また上記のような想定解法での解答はなく、以下のような解答を頂きました。DNATの解法は、想定はしていたのですがCoreDNSは完全に想定しなかったので、確かにそういう方法もあるのかと思いました。(self checkとは?という感じではありますが、問題の終了条件を満たせるので満点としました。)

  • CoreDNSのレコードを変更しingress controllerのPODのIPアドレスを名前解決するようにする
  • lbでk8sのいずれかのノードにDNATをする
 /
カテゴリー

問題名

なぜか動きません!

概要

あなたは研修グループに所属にしているエンジニア兼先生です。
研修にて、サーバー上でDockerを用いてサービスを構築する研修課題を出題しました。
課題はDocker Compose を使って複数のイメージを起動してみる。という課題でした。ある一人の受講生がエラーが発生し、解決できないと相談しにきました。
エラーを解消し起動を行いなさい。

前提条件

サーバーのルール:Dockerイメージは公式イメージのみ
Docker Hubのサインインはしない

課題
次回,使用するためにWebサーバーとdbをdocker-compose.ymlとDockerfileを使って構築しましょう.
WebサーバーはNGINX,データベースはMariaDBを使用してください.

初期状態

  • /home/user/homework01に課題で使用したdocker-compose.ymlDockerfileが保存されている
  • $ docker-compose up -d に失敗する

終了状態

  • 課題の条件を達成する
  • $ docker-compose up -dが成功し、$ docker-compose psにて全てのコンテナのstatusupしている
  • 解答提出時にエラーが発生した原因を記述する

解説

初めて環境構築を行っていく上で間違えてしまう点、ARMとx86のアーキテクチャの違いと起動ログをみて原因を究明するということに焦点を当てて作成した問題になります。
まず、初期状態にて起動を行うと

$ docker-compose up
Starting homework01_db_1    ... done
Starting homework01_nginx_1 ... done
Attaching to homework01_nginx_1, homework01_db_1
db_1     | standard_init_linux.go:211: exec user process caused "exec format error"
nginx_1  | standard_init_linux.go:211: exec user process caused "exec format error"
homework01_db_1 exited with code 1
homework01_nginx_1 exited with code 1

と,起動に失敗します。

出題時のファイル

$ cat Dockerfile
FROM mariadb@sha256:eacab2a85f2692a71bbecec0ec1d4eab0a813409bc4760b2d15269b05aa2bafb
$ cat docker-compose.yml
version: '3'
services:
    nginx:
            image: nginx@sha256:8789e3c472689faa3849023e5272e887982f0714a9e3c89e4786b8cf614db2cf
    db:
            build: ./

第一関門

初めに、
全角スペースをDockerfileに混入されていることが原因で以下のエラーが出現します。

$ docker-compose build 
nginx uses an image, skipping
Building db
ERROR: Dockerfile parse error line 1: unknown instruction: FROM MARIADB@SHA256:EACAB2A85F2692A71BBECEC0EC1D4EAB0A813409BC4760B2D15269B05AA2BAFB

よってDockerfileの中にある全角を半角に置換します。

第二関門

docker のイメージ情報をみて使用イメージがVMで使用しているアーキテクチャのx86アーキテクチャCPU向けであることの確認します。

$ docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               <none>              2b71a68aa246        6 days ago          45.3MB
homework01_db       latest              d8d6819532a3        8 days ago          387MB
mariadb             <none>              d8d6819532a3        8 days ago          387MB
$ docker image inspect 2b71a6
.....
"Architecture": "arm",
.....

今回のVMはx86のアーキテクチャを使用してるので、ここの点を変更します。

第三関門

docker-conpsoe.ymlに環境設定の必要事項が未記入のため下記のエラーが出てMariaDBが起動していない。

db_1     | 2021-03-03 17:41:07+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
db_1     |     You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

docker-compose.ymlにて、必要事項を記入する

以上の3つの問題点を解決して起動をすると

$ docker-compose ps
       Name                     Command               State    Ports  
----------------------------------------------------------------------
homework01_db_1      docker-entrypoint.sh mysqld      Up      3306/tcp
homework01_nginx_1   /docker-entrypoint.sh ngin ...   Up      80/tcp  

無事に起動をすることができました。

正解例

$ cat Dockerfile
FROM mariadb@sha256:d866e756c68fce525419ee27e1d76a874c54072e49dfd591891acd28f95760fc
$ cat docker-compose.yml
version: '3'
services:
    nginx:
            image: nginx@sha256:3293470d994e1da29ba232de1809b4c88beb1f3c8352c0c171f8796038888493
    db:
            build: ./
            environment:
                    MYSQL_ROOT_PASSWORD: example

採点基準

以下の基準にて、問題環境と解答文の原因記載の両者ができて得点とする

  • 全角スペースの撤去(Dockefile内) 20%
  • Nginx/MariaDBのx86のイメージに変更(解答にてアーキテクチャの問題と明記している) 40%
  • MariaDBの必要設定を行う(解答分にて変更点を記載もしくはエラーの要因を記入) 40%