# Elastic Observability 實作體驗營 (2023.09 update)
:::info
**本頁面縮網址:** https://hackmd.io/@estraining/DevOpsDaysTaipei2022
**講者:** [喬叔 (Joe Wu)](https://training.onedoggo.com/about-me)
**Facebook 粉絲頁:** [喬叔 - Elastic Stack 技術交流](https://www.facebook.com/Joe.ElasticStack/)
:::
## 行前準備
### 操作電腦需求
- 最少 **16GB** 以上的 RAM
- 最少 30GB 以上的 Disk Space
- MacOS, Linux, Windows 皆可,但請不要用太舊的作業系統
:::danger
:exclamation:請注意,由於這次工作坊執行的 docker containers 數量眾多,記憶體的要求較高,如果記憶體不到 16GB 的話幾乎很難順利運作,若是要開雲端主機的話,可以參考 - [如果要使用雲端主機,可以設定-SSH-Tunnel-來存取](#如果要使用雲端主機,可以設定-SSH-Tunnel-來存取) 的設定方式。
:::
### 準備執行環境
請先在電腦中安裝以下所需的執行環境:
- Docker
- Docker Compose ([安裝說明](https://docs.docker.com/compose/install/))
- Python3 ([安裝說明](https://github.com/elastic/apm-integration-testing#python-3))
- Git (會簡單的 `git clone`, `git pull`, `git checkout` 即可。)
### 準備好 Docker Images
這次的工作坊,使用的是 Elastic 在 GitHub 所提供的 [apm-integration-testing](https://github.com/elastic/apm-integration-testing) 開源專案。
因為在操作時會需要 build Docker image 以及下載一些 Elastic Stack 的 Docker images,為了避免工作坊的時間被佔用在處理 build & download,建議請大家先完成以下的步驟。
:::danger
:exclamation:請注意,喬叔有特別為了這次工作坊進行一些準備,所以請直接到喬叔 fork 出來的 GitHub 專案進行下載 [https://github.com/joecwu/apm-integration-testing/](https://github.com/joecwu/apm-integration-testing/),不要下載到 Elastic 官方版的哦!
:::
1. 取得 apm-integration-testing 的檔案。
可使用 `git clone` 的指令,或是直接[下載 Zip 壓縮檔](https://github.com/joecwu/apm-integration-testing/archive/refs/heads/main.zip)。
```
git clone https://github.com/joecwu/apm-integration-testing.git
```
2. 準備好 Docker Images
有以下兩種選擇,自行 build 或是直接抓喬叔準備好的 docker images.
2-1. **自行 build:**
在專案的根路徑下,執行以下 `compose.py build` 的指令,以建立及下載所需要使用到的 Docker images:
Mac or Linux:
```
./scripts/compose.py build --release --with-opbeans-java --with-opbeans-ruby --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
Windows:
```
python .\scripts\compose.py build --release --with-opbeans-java --with-opbeans-ruby --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
2-2. **直接使用喬叔 build 好的 docker image**
**Mac M1**:
```
docker-compose -f ./docker-compose-arm64.yml pull
```
**Linux**:
```
docker-compose -f ./docker-compose-linux.yml pull
```
**Windows**:
```
docker-compose -f ./docker-compose-windows.yml pull
```
:::danger
其他平台需自行 build,否則 `opbeans-go` 和 `opbeans-rum` 會無法成功執行。
:::
3. 確認 Docker Images 已被成功建置及下載。
使用 `docker images` 指令,確認有存在下列 Docker Images.

4. 多確認是否能正常運作 Docker Cotainers
使用自行 build,請用:`docker-compose up -d`
若是使用另外的 yml 檔,請指定 `-f` 參數:`docker-compose -f ./docker-compose-linux.yml up -d`
請確認 containers 都能正常運作 (狀態為 `healthy`),若有問題,可先參考 [FAQ](#FAQ)
## Elastic APM Integration Test 簡介
[APM Integration Testing](https://github.com/elastic/apm-integration-testing) 是一個公開在 GitHub 的開放原始碼的專案,這個專案主要語言是用 Python 撰寫,並且使用 Docker 來運作 Elastic Stack 的各種服務以及 opbeans 這個 Demo 專用的庫存管理系統,讓我們能夠擁有一個 Elastic APM 所需要執行的情境,並且能夠將當中的某些元件替換成真實運作的版本,可以協助開發人員進行 debug,或是協助整合測試 (Integration Test) 所需使用的複雜的環境。
### 包含的角色
以下幾種角色,是 APM Integration Testing 的 Docker Containers 運作起來時,裡面有的角色:
- Elastic Stack
- Elasticsearch
- Kibana
- APM Server
- Heartbeat
- Filebeat
- Metricbeat
- Packetbeat
- opbeans 庫存管理系統的各種語言版本的實作,並且埋入 APM Agent
- opbeans-go
- opbeans-java
- opbeans-ruby
- opbeans-dotnet
- opbeans-node
- opbeans-python
- opbeans-php
- opbeans 所使用到的 Database 或是 Cache 等服務
- PostgreSQL
- Redis
- 針對 opbeans 庫存管理的系統,使用 [apm-agent-rum-js](https://github.com/elastic/apm-agent-rum-js),實作 Real User Monitoring
- opbeans-rum
- 自動模擬存取流量的 opbeans-load-generator
- 專門製造錯誤情況發生,讓壓測能更擬真的 Dyno. (僅支援 opbeans-python)
### 運作示範
下圖是 Kibana > Observability > Trace > Service Map 的截圖。
:::warning
請留意,每個 opbeans 即是一個完整的 web 專案,本身就可以獨立運作,但是當 apm-integration-testing 透過 docker-compose 啟動時,如果同時執行超過一種以上的 `opbeans-XXX`,會在執行時隨機存取其他 `opbeans-XXX`,創造出 service 與 service 之間互相溝通的存取,以模擬多層次或是分散式架構系統的運作情境。
:::

## 任務一:將 apm-integration-test 運作起來
### 1. 準備執行環境
請確認電腦已安裝好下列必要的執行環境:
- Docker
- Docker Compose ([安裝說明](https://docs.docker.com/compose/install/))
- Python3 ([安裝說明](https://github.com/joecwu/apm-integration-testing#python-3))
### 2. 安裝指令
#### 2.1 自行 build & start
透過執行 `compose.py start` 產生並執行 `docker-compose.yml`。
Mac or Linux:
```
./scripts/compose.py start --release --with-opbeans-java --with-opbeans-ruby --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
Windows:
```
python .\scripts\compose.py start --release --with-opbeans-java --with-opbeans-ruby --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
:::warning
如果系統資源不足,跑不動太多的 Containers 的話,可以減少一些 `--with-opbeans-{XXX}`。
建議最少要啟動 `opbeans-node` 及 `opbeans-rum`。
例如:
Mac or Linux:
```
./scripts/compose.py start --release --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
Windows:
```
python .\scripts\compose.py start --release --with-opbeans-python --with-opbeans-go --with-opbeans-node --with-opbeans-rum --with-filebeat --with-metricbeat --with-heartbeat 8.9.0
```
:::
:::info
由於 `opbeans-dotnet` .Net 的版本在 Apple M1 系列 CPU 建置時可能會有問題,所以我們這次直接略過不使用 `opbeans-dotnet` 版本,若你是 Windows 的環境,且硬體資源充足,想嘗試的話,還是可以加入 `--with-opbeans-dotnet`
:::
#### 2.2 直接拉 Docker Image (略過 build)
:::warning
請記得拉最新的 main branch 的 code
:::
**Mac M1**:
```
docker-compose -f ./docker-compose-arm64.yml up -d
```
**Linux**:
```
docker-compose -f ./docker-compose-linux.yml up -d
```
**Windows**:
```
docker-compose -f ./docker-compose-windows.yml up -d
```
:::danger
其他平台需自行 build,否則 `opbeans-go` 和 `opbeans-rum` 會無法成功執行。
:::
### 3. 確認安裝完成
使用 `docker-compose ps -a` 或是 `docker ps -a` 查看執行中的 containers。
### 4. 登入 Kibana
Kibana: http://localhost:5601
預設管理者帳號:`admin`
預設密碼:`changeme`

### 5. 查看 Kibana > Stack Monitoring
進入 [Kibana > Stack Monitoring](http://localhost:5601/app/monitoring),可以成功查看 Elasticsearch Cluster 正常的運作,同時也有 Kibana 正在運作中。

## 任務二:收集 Opbeans 各服務所產生的 Logs
### 1. 設定 `filebeat.yml`
修改 `./docker/filebeat/filebeat.yml`
在 **## autodiscover** 的區塊裡,填加以下的設定。
```yaml
filebeat.autodiscover:
providers:
- type: docker
templates:
- condition:
contains:
docker.container.name: "opbeans-"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
include_lines: ['^{']
tail_files: true
processors:
- add_tags:
tags: [json]
target: "parser_type"
- decode_json_fields:
fields:
- message
target: ""
overwrite_keys: true
add_error_key: true
- drop_fields:
fields:
- service
- event
- url
- error
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
fields_under_root: true
- condition:
contains:
docker.container.name: "opbeans-"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
multiline.pattern: '^[[:blank:]]'
multiline.negate: false
multiline.match: after
exclude_lines: ['^{']
processors:
- add_tags:
tags: [no_json]
target: "parser_type"
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "kibana"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "elasticsearch"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "metricbeat"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "heartbeat"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "filebeat"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.name: "apm-server"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
json.add_error_key: true
json.overwrite_keys: true
json.keys_under_root: true
processors:
- rename:
fields:
- from: "error"
to: "error_apm_server"
ignore_missing: false
fail_on_error: true
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
- condition:
contains:
docker.container.image: redis
config:
- module: redis
log:
input:
type: container
paths:
- /var/lib/docker/containers/*/${data.docker.container.id}-json.log
- condition:
contains:
docker.container.image: "postgres"
config:
- module: postgresql
log:
input:
type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
- condition:
and:
- not:
contains:
docker.container.name: "apm-server"
- not:
contains:
docker.container.name: "filebeat"
- not:
contains:
docker.container.name: "heartbeat"
- not:
contains:
docker.container.name: "kibana"
- not:
contains:
docker.container.name: "metricbeat"
- not:
contains:
docker.container.name: "opbeans-"
- not:
contains:
docker.container.name: "postgres"
config:
- type: container
paths:
- "/var/lib/docker/containers/*/${data.docker.container.id}-json.log"
tail_files: true
processors:
- copy_fields:
fields:
- from: docker.container.labels.org_label-schema_name
to: event.dataset
fail_on_error: false
ignore_missing: true
```
### 2. 重新啟動 Filebeat
```
docker-compose restart filebeat
```
### 3. 查看 Log 以確認 Filebeat 運作是否正常 (Optional)
```
docker-compose logs -f filebeat
```
### 4. 進入 Kibana 查看 Containers 的 Logs。
接下來,可以進入 Kibana (http://localhost:5601) 在 Observability > Logs > Stream (http://localhost:5601/app/logs/stream) 查看是否 Log 有成功傳送到 Elasticsearch 中。
:::info
可以在搜尋框中,嘗試打入 `event.dataset: opbeans-`,**自動完成**的功能會列出目前有的 `event.dataset` 的值供選取,如果有成功將 `opbeans-node`, `opbeans-python`, `opbeans-go`...這些服務的 Logs 收集到,就可以針對這些服務進行篩選。
:::

## 任務三:收集 Opbeans 各服務所產生的 Metrics
### 1. 設定 `metricbeat.yml`
修改 `./docker/metricbeat/metricbeat.yml`
在 `metricbeat.monitors` 的部份配置以下設定:
```yaml
metricbeat.modules:
- module: golang
metricsets: ["expvar", "heap"]
period: 10s
hosts: ["${APM_SERVER_PPROF_HOST:apm-server:6060}"]
heap.path: "/debug/vars"
expvar:
namespace: "apm-server"
path: "/debug/vars"
- module: docker
metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"]
hosts: ["unix:///var/run/docker.sock"]
period: 10s
```
在 `metricbeat.autodiscover` 的部份配置以下設定:
```yaml
metricbeat.autodiscover:
providers:
- type: docker
hints.enabled: true
templates:
- condition:
contains:
docker.container.image: "redis"
config:
- module: redis
metricsets: ["info", "keyspace"]
hosts: "${data.host}:6379"
- condition:
contains:
docker.container.image: "postgres"
config:
- module: postgresql
metricsets: ["database", "bgwriter", "activity"]
hosts: ["postgres://${data.host}:5432?sslmode=disable"]
password: verysecure
username: postgres
- condition:
contains:
docker.container.image: "kafka"
config:
- module: kafka
metricsets: ["consumergroup", "partition"]
period: 10s
hosts: "${data.host}:9092"
- condition:
contains:
docker.container.image: "logstash"
config:
- module: logstash
metricsets: ["node", "node_stats"]
period: 10s
hosts: "${data.host}:9600"
```
### 2. 重新啟動 Metricbeat
```
docker-compose restart metricbeat
```
### 3. 從 Kibana 以確認 Metricbeat 運作是否正常
接下來,可以進入 Kibana 在 Observability > Infrastructure > Inventory (http://localhost:5601/app/metrics/inventory) ,切換 Show 為 `Docker Containers` 查看是否 Metricbeat 有成功傳送資料到 Elasticsearch 中。

## 任務四:收集 Opbeans 各服務所產生的 Traces
:::warning
這個部份由於需要改 Code,這次 Workshop 時間有限,不在這邊練習,目前執行的版本,已經都實作好 APM Agents 的部份,同時 APM Server 也透過 Elastic Agent 在運作了。
:::
除了參考 Elastic 官方 [APM 的說明文件](https://www.elastic.co/guide/en/apm/index.html),可以配合從 [Elastic GitHub 搜尋 `opbeans-`](https://github.com/elastic?q=opbeans-&type=all&language=&sort=) ,查看目前所執行的 opbeans 各種語系專案的實作方式。
例如 `opbeans-node` 的 NodeJS 的 [`server.js`](https://github.com/elastic/opbeans-node/blob/main/server.js) 實作參考。
## 任務五:監控 Opbeans 的服務運作狀態 (Uptime)
### 設定 `heartbeat.yml`
修改 `./docker/heartbeat/heartbeat.yml`
在 `heartbeat.monitors` 的部份配置以下設定:
```yaml
heartbeat.monitors:
- type: http
name: onedoggo training web
schedule: '@every 60s'
urls: ["https://training.onedoggo.com/"]
check.response.status: 200
tags: ["3rdParty"]
fields:
env: production
- type: http
name: "opbeans web"
schedule: '@every 10s'
urls: [
"http://opbeans-node:3000",
"http://opbeans-java:3000",
"http://opbeans-python:3000",
"http://opbeans-go:3000",
"http://opbeans-ruby:3000"
]
check.response.status: 200
tags: ["web", "opbeans"]
fields:
env: production
```
另外在 `heartbeat.autodiscover` 的部份配置以下設定:
```yaml
heartbeat.autodiscover:
providers:
- type: docker
templates:
- condition:
contains:
docker.container.image: redis
config:
- type: tcp
name: "${data.docker.container.name}"
hosts: ["${data.host}:${data.port}"]
schedule: "@every 1s"
timeout: 1s
tags: ["DB", "container"]
- condition:
and:
- contains:
docker.container.image: opbeans
- not:
contains:
docker.container.name: opbeans-load-generator
config:
- type: http
name: "${data.docker.container.name}"
urls: ["http://${data.host}:${data.port}"]
schedule: "@every 5s"
timeout: 1s
tags: ["opbeans","container"]
```
### 重新啟動 Heartbeat
```
docker-compoes restart heartbeat
```
### 從 Kibana 以確認 Heartbeat 運作是否正常
接下來,可以進入 Kibana 在 Observability > Uptime > Monitors (http://localhost:5601/app/uptime) 查看是否 Heartbeat 的 monitors 有成功傳送到 Elasticsearch 中。
### 加強版設定
增加 `heartbeat.monitors` 的配置:
- 從 container 外部對於 Redis 的監控
- 從 container 外部存取 opbeans web 的監控
```yaml
heartbeat.monitors:
- type: http
name: onedoggo training web
schedule: '@every 60s'
urls: ["https://training.onedoggo.com/"]
check.response.status: 200
tags: ["3rdParty"]
fields:
env: production
- type: http
name: "opbeans web"
schedule: '@every 10s'
urls: [
"http://opbeans-node:3000",
"http://opbeans-java:3000",
"http://opbeans-python:3000",
"http://opbeans-go:3000",
"http://opbeans-ruby:3000"
]
check.response.status: 200
tags: ["web", "opbeans"]
fields:
env: production
# - type: http
# name: "opbeans web public access"
# schedule: '@every 10s'
# urls: [
## localhost 要換成 IP,否則 Docker Container 內部存取 localhost 會是錯誤的。
# "http://localhost:3000",
# "http://localhost:3001",
# "http://localhost:3002",
# "http://localhost:3003",
# "http://localhost:8000"
# ]
# check.response.status: 200
# tags: ["web", "opbeans"]
# fields:
# env: production
- type: tcp
name: redis healthcheck
schedule: '@every 5s'
hosts: ["redis:6379"]
tags: ["DB"]
fields:
env: production
```
## 任務六:設定異常時的主動通知 - Alert
### 1. Service Level Indicator & Objective - 1
建立新的 Alert,選擇 Rule Type 為 **Uptime monitor status**,並依照需求填入設定。
依需求建立 `Web Uptime SLI-1`

Actions 的部份,以 Index 為例,建立新的 Index Connector:

**Document to index** 的 index document 簡單範例:
```
{
"rule_id": "{{rule.id}}",
"rule_name": "{{rule.name}}",
"alert_id": "{{alert.id}}",
"context_message": "{{context.message}}"
}
```

### 2. Service Level Indicator & Objective - 2
建立新的 Alert,選擇 Rule Type 為 **APM Latency threshold**,並依照需求填入設定。
依需求建立 `Web Latency SLI-2-1`

依需求建立 `Web Latency SLI-2-2`

**Document to index** 的 index document 使用一樣的簡單範例:
```
{
"rule_id": "{{rule.id}}",
"rule_name": "{{rule.name}}",
"alert_id": "{{alert.id}}",
"context_message": "{{context.message}}"
}
```
### 3. 建立完成後,可以在 Manage Rules 的頁面查看結果。
在 [Kibana > Alert > Manage Rules (右上角)](http://localhost:5601/app/observability/alerts/rules) 可以查看 Rules 設定結果。

## 使用 Elastic Observability 查找問題的技巧
### 別忘記內建的 Dashboard
- [Metricbeat Docker] Overview ECS
- [Filebeat PostgreSQL] Overview ECS
- [Metricbeat PostgreSQL] Database Overview
### 利用 Machine Learning
- Logs
- Anomalies: 主要是針對 log entry rates (輸入率) 來進行異常的判斷。
- Categories: 依照收集到的 Logs 進行分類,前且顯示總數量、Datasets 的來源、並且借由 Trend (趨勢) 的變化及數量來快速判斷異常的狀況。
###
## FAQ
### 使用 Apple M2 (ARM64/v8) 無法順利執行 `opbeans-xxx` 的 containers 該怎麼辦?
若使用 Docker Desktop,請先將 Rosetta 模擬 AMD64 的功能啟用。

### 執行 `composer.py` 時 Docker build 出現 `GPG error`
docker 出現 GPG error: At least one invalid signature was encountered 相關問題及解決辦法。
> There are a few reasons why you encounter these errors:
>
> There might be an issue with the existing cache and/or disc space. In order to fix it you need to clear the APT cache by executing: sudo apt-get clean and sudo apt-get update.
>
> The same goes with existing docker images. Execute: docker image prune -f and docker container prune -f in order to remove unused data and free disc space.
>
> If you don’t care about the security risks, you can try to run the apt-get command with the --allow-unauthenticated or --allow-insecure-repositories flag. According to the docs:
>
> Ignore if packages can’t be authenticated and don’t prompt about it. This can be useful while working with local repositories, but is a huge security risk if data authenticity isn’t ensured in another way by the user itself.
>
> Finally, on MacOS, where Docker runs inside a dedicated VM, you may need to increase the disk available to Docker from the Docker Desktop application (Settings -> Resources -> Advanced -> Disk image size).
:::danger
執行以下指令會將你的 Docker 環境清空,包含 images, dangling build caches, containers,請確認後再操作。
:::
```
docker container prune
docker image prune -a
docker system prune
docker system df
```
### 啟動時,容器異常中止
查看 docker-compose logs `{container_name}` 時,發現以下的錯誤:
```
exec /usr/bin/dumb-init: exec format error
```
這代表該 Docker Image 不是用對應的 platform 所建置,需自行 build imgae 才能使用。
### 啟動時,發生 `unhealthy` 的錯誤
```
ERROR: for opbeans-node Container "907fc7a0c9be" is unhealthy.
ERROR: for opbeans-load-generator Container "24e4d86c54ed" is unhealthy.
ERROR: Encountered errors while bringing up the project.
Traceback (most recent call last):
File "/Users/joecwu/projects/joecwu/apm-integration-testing/./scripts/compose.py", line 31, in <module>
main()
File "/Users/joecwu/projects/joecwu/apm-integration-testing/./scripts/compose.py", line 17, in main
setup()
File "/Users/joecwu/projects/joecwu/apm-integration-testing/scripts/modules/cli.py", line 213, in __call__
self.args.func()
File "/Users/joecwu/projects/joecwu/apm-integration-testing/scripts/modules/cli.py", line 590, in start_handler
self.build_start_handler("start")
File "/Users/joecwu/projects/joecwu/apm-integration-testing/scripts/modules/cli.py", line 782, in build_start_handler
self.run_docker_compose_process(docker_compose_cmd + up_params)
File "/Users/joecwu/projects/joecwu/apm-integration-testing/scripts/modules/cli.py", line 476, in run_docker_compose_process
subprocess.check_call(docker_compose_cmd)
File "/Users/joecwu/.pyenv/versions/3.9.2/lib/python3.9/subprocess.py", line 373, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['docker-compose', '-f', '/Users/joecwu/projects/joecwu/apm-integration-testing/docker-compose.yml', 'up', '-d']' returned non-zero exit status 1.
```
有可能是當下某一些有相依性的 service 還沒有正常的啟動,可以先重新使用 `docker-compose` 啟動一次試試,看看是否有改善。
```
docker-compose up -d
```
若是依然有服務沒辦法正常啟動,可使用 `docker ps -a` 查看沒有正常啟動的服務是哪些,並進一步使用 `docker logs {{DockerContainerName}}` 查看錯誤訊息。
### `opbeans-dotnet` 在 Apple M1 無法啟動
使用 `docker logs localtesting_8.9.0_opbeans-dotnet` 查看,發現以下錯誤:
```
Failed to resolve full path of the current executable [/proc/self/exe]
```
:::warning
在這次 Workshop 中,若是使用 Apple M1,我們先不啟用 `opbeans-dotnet`
:::
### 如果已經啟動過,但想要清空環境,重新再來
先清除所有正在運作中的 containers,以下方式二擇一:
1. 使用 `composer.py`
```
./scripts/compose.py stop
```
2. 使用 `docker-compose`
```
docker-compose down
```
如果有需要,可以一併刪除已產生的 docker volume.
```
docker volume rm apm-integration-testing_esdata
docker volume rm apm-integration-testing_pgdata
```
### 如果要使用雲端主機,可以設定 SSH Tunnel 來存取
`~/.ssh/config` 的參考設定如下:
```
Host gcptunnel
HostName <my.gcp.host.ip>
IdentityFile ~/.ssh/google_compute_engine <--- yours may differ
User jamie <--- yours probably differs
Compression yes
ExitOnForwardFailure no
LocalForward 3000 127.0.0.1:3000
LocalForward 3001 127.0.0.1:3001
LocalForward 3002 127.0.0.1:3002
LocalForward 3003 127.0.0.1:3003
LocalForward 3004 127.0.0.1:80
LocalForward 5601 127.0.0.1:5601
LocalForward 8000 127.0.0.1:8000
LocalForward 9200 127.0.0.1:9200
LocalForward 9222 127.0.0.1:9222
```
以上述的例子,設定完成後,執行 `ssh gcptunnel` 即可將本機的 port 轉接到雲端主機。
## 參考資料
- 喬叔帶你上手 Elastic Stack - 探索與實踐 Observability 系列 - [使用 APM-Integratoin-Testing 建立 Elastic APM 的模擬環境](https://training.onedoggo.com/tech-sharing/uncle-joe-teach-es-elastc-observability/traces-guan-cha-ying-yong-cheng-shi-de-xiao-neng-ping-jing/shi-yong-apmintegratointesting-jian-li-elastic-apm-de-mo-ni-huan-jing)
- Elastic Demo Site:
- [https://demo.elastic.co](https://demo.elastic.co)
- Observability: [https://demo.elastic.co/app/observability/overview](https://demo.elastic.co/app/observability/overview)
:::success
以上有關 `.yaml` 檔的修改,已 commit 在喬叔 GitHub 的 `2022-devopsdays-workshop` branch 之中,可以直接 `git checkout 2022-devopsdays-workshop`,或是[點此](https://github.com/joecwu/apm-integration-testing/archive/refs/heads/2022-devopsdays-workshop.zip)下載。
:::