1. ingress란

클러스터 외부에서 내부로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음.
외부에서 접근가능한 url을 사용할 수 있게 하고,
트래픽 로드밸런싱도 해주고,
ssl 인증서 처리,
도메인 기반 가상 호스팅을 제공.
ingress 자체는 이런 규칙들을 정의해둔 자원.
실제 동작하게 해주는게 ingress controller.
클라우드서비스를 사용하는것이 아니라면
ingress와 ingress controller를 직접 연동해주어야함.

이때 가장 많이 사용되는게 kubernetes에서 제공하는 ingress-nginx.

2. ingress-nginx 설치, 사용.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

kubectl expose deploy nginx-ingress-controller --type=NodePort -n ingress-nginx

kubectl apply -f test.yaml

# 확인
kubectl describe ingress test

kubctl apply -f deployments-nginx.yaml

kubectl expose deploy nginx-deployment --name s1

 

  • test.yaml 내용

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: test
    annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
    rules:
     - host: xxx.xxx.xx
    paths:
     - path: /foos1
    backend:
    serviceName: s1
    servicePort: 80
     - path: /bars2
    backend:
    serviceName: s2
    servicePort: 80
     - host: xxx.xxx.xx
    http:
    paths:
     - backend:
    serviceName: s2
    servicePort: 80

     

  • deployments-nginx.yaml 내용.
    kind: Deployment
    metadata:
    name: nginx-deployment
    labels:
    app: nginx
    spec:
    replicas: 3
    selector:
    matchLabels:
    app: nginx
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx
    ports:
    - containerPort: 80

 

3. 접근

kubectl get services --all-namespaces 에서 나온 port와 s1에 설정한 host, path를 이용하여
xxx.xxx.xxx:31536/foos1 로 접근 가능.

 

저는 소스관리를 위해 github을 사용중입니다.

ssh key 설정을 해두지 않으면 commit, push 할때 마다 로그인 정보를 입력해야하는 번거로움이 있습니다.

그런데 ssh key를 github deploy key에 등록해주면 그런 번거로움을 덜 수 있습니다.

 

1. git clone을 할때 http가 아닌 ssh 주소를 사용하세요

텍스트 추가

대표사진 삭제

사진 설명을 입력하세요.

텍스트 추가

 

2. 작업하는 서버에서 ssh key를 생성합니다.

ssh-keygen -t rsa -C “your_email@example.com”

 

3. 생성된 public key를 github settings > deploy keys에 push권한을 체크해서 등록해줍니다.

cat ~/.ssh/id_rsa.pub

 

텍스트 추가

대표사진 삭제

사진 설명을 입력하세요.

텍스트 추가

 

 

 

이제는 매번 로그인 하지 않아도 되네요 ^^

 

 

mysql8로 버전업이 됨에 따라 기존에 사용중이던 hibernate, mysql-connector-java등 version을 올리고 관련 conf수정하였다

수정 부분 요약.

  1. pom.xml
    hibernate.version=5.3.1.Final
    (hibernate-entitymanager 삭제, hibernate-validator 추가 )

  2. application.properties
    hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

  3. mysql8.0 user 권한부여

구체적인 내용.

  1. pom.xml 1.8 0.0.1
     <properties>
         <java.version>1.8</java.version>
         <twig-service.version>0.0.1</twig-service.version>
-        <hibernate.version>5.0.3.Final</hibernate.version>
+        <hibernate.version>5.3.1.Final</hibernate.version>
         <hibernate-javax-persistence.version>1.0.0.Final</hibernate-javax-persistence.version>
         <commons-configuration.version>1.10</commons-configuration.version>
-        <mariadb-java-client.version>1.3.0</mariadb-java-client.version>
+        <mariadb-java-client.version>2.4.1</mariadb-java-client.version>
         <querydsl.version>4.1.4</querydsl.version>
         <spring-data-mock.version>1.1.4</spring-data-mock.version>
+       <hibernate.validator.version>6.0.10.Final</hibernate.validator.version>
     </properties>

-       <dependency>
-            <groupId>org.hibernate</groupId>
-             <artifactId>hibernate-entitymanager</artifactId>
-             <version>${hibernate.version}</version>
-       </dependency>
+       <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+           <version>${hibernate.validator.version}</version>
+       </dependency>
        <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
-            <version>5.1.37</version>
+            <version>8.0.16</version>
        </dependency>

 

  1. application.properties
    hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

  2. mysql설정

    - 아래와 같이 mysql conf수정
     default password plugin 설정 추가

    [mysqld]
    default-authentication-plugin=mysql_native_password

       - mysql 내 계정 생성시 문법 변경 및 인증 타입 명시  
         grant 에는 identified 삭제  
         create 시에 with mysql\_native\_password 추가

 create user 'mydb'@'%' IDENTIFIED WITH mysql_native_password BY 'YOURPASSWORD';
 GRANT ALL PRIVILEGES on mydb.* to 'myuser'@'%' WITH GRANT OPTION;

maven에 새 jar를 추가하고 application을 실행해보니 아래와 같은 메세지가 나온다.

오류메세지

:A child container failed during start  
[java.util.concurrent.ExecutionException:](java.util.concurrent.ExecutionException:) [org.apache.catalina.LifecycleException:](org.apache.catalina.LifecycleException:) Failed to start component \[StandardEngine\[Tomcat\].StandardHost\[localhost\].StandardContext\[\]\]  
at [java.util.concurrent.FutureTask.report(FutureTask.java:122)](java.util.concurrent.FutureTask.report(FutureTask.java:122)) ~\[?:1.8.0\_77\]  
at [java.util.concurrent.FutureTask.get(FutureTask.java:192)](java.util.concurrent.FutureTask.get(FutureTask.java:192)) ~\[?:1.8.0\_77\]  
at [org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:911)](org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:911)) \[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:890)](org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:890)) \[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)](org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)) \[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403)](org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403)) \[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)](org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)) \[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [java.util.concurrent.FutureTask.run(FutureTask.java:266)](java.util.concurrent.FutureTask.run(FutureTask.java:266)) \[?:1.8.0\_77\]  
at [java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)](java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)) \[?:1.8.0\_77\]  
at [java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)](java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)) \[?:1.8.0\_77\]  
at [java.lang.Thread.run(Thread.java:745)](java.lang.Thread.run(Thread.java:745)) \[?:1.8.0\_77\]  
Caused by: [org.apache.catalina.LifecycleException:](org.apache.catalina.LifecycleException:) Failed to start component \[StandardEngine\[Tomcat\].StandardHost\[localhost\].StandardContext\[\]\]  
at [org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)](org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)) ~\[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
... 6 more  
Caused by: [org.apache.catalina.LifecycleException:](org.apache.catalina.LifecycleException:) Failed to start component \[Pipeline\[StandardEngine\[Tomcat\].StandardHost\[localhost\].StandardContext\[\]\]\]  
at [org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)](org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)) ~\[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  
at [org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5099)](org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5099)) ~\[[tomcat-embed-core-8.5.5.jar:8.5.5\]](tomcat-embed-core-8.5.5.jar:8.5.5])  

해결방법

검색해보니 servlet-api.jar를 exclude하라는 말이 많이 나왔는데
나의 경우 아래 설정을 pom에 추가하니 실행 성공하였다.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

provided 는 무엇을 의미하는지?

This scope is used to mark dependencies that should be provided at runtime by JDK or a container, hence the name.

A good use case for this scope would be a web application deployed in some container, where the container already provides some libraries itself.
컨테이너에서 deploy도는 어플리케이션에서 컨테이너는 이미 자체적인 라이브러리를 제공한다.

For example, a web server that already provides the Servlet API at runtime, thus in our project, those dependencies can be defined with the provided scope:
런타임에 의존성을 가지지 않고 컴파일/테스트단계에서만 제공되는 dependency.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

The provided dependencies are available only at compile-time and in the test classpath of the project; what's more, they aren't transitive.

라이브러리 의존성을 피하기 위한 방법이리라.

  • embedding 벡터를 합치기 위해서는 np.zeros()를 통해 초기화를 진행하고
  • 초기화된 embed에 누적해서 벡터의 값을 더해주고
  • 마지막으로 합치는 벡터의 개수로 나눠준다.
def agg_embed(terms):
  embed = np.zeros(128) 
  for term in terms: 
      embed += np.array(term['embedding'])
  embed /= len(terms)
  return embed

sentence embedding을 얻었다면, 두개의 유사도를 계산하기 위해서는 cosine similarity를 이용해서 계산을 해야한다.

pandas에서 udf를 통해 계산하는 방법은 아래와 같다.
keywordcontext에는 문자열이 들어가면 된다.

ex: keyword: 안녕, context: 잘가요. 멀리 안가요


import numpy as np
from scipy import spatial

def sim(x, y): 
  embed1 = get_embed(x)  
  embed2 = get_embed(y) 
  return 1 - spatial.distance.cosine(embed1, embed2)

def sim_udf(x): 
  sim_value = sim(x['keyword'], x['context'])  
  return sim_value 


df['cosim'] = df.apply(sim_udf, axis=1)

python에서 Counter를 이용하면 list로 받은 값들의 개수를 계산한 해서 아래와 같이 결과를 받을 수 있다.

from collections import Counter
Counter(['apple','red','apple','red','red','pear'])
Counter({'red': 3, 'apple': 2, 'pear': 1})
  • 파이썬에서 한글, 영문, 숫자가 포함된 문자열에서 한글만 추출하는 방법에 대해서 설명한다.
  • python을 이용해서 한글처리를 하다보면 ㅋㅋㅋ, ㅎㅎㅎ와 같은 모음, 자음이 따로 있는 경우가 있는데 보통은 의미가 없다. 감정을 나타내는 문제에서는 의미가 있으려나...
  • 모/자음만 있는 한글을 추려내는 방법은 정규식을 사용하면 쉽게 추출, 제거 할 수 있다.

정규식에서 일치되는 부분을 리스트로 저장

import re

text = "ㅋㅋㅋ 안녕하세요"
# 정규식에서 일치되는 부분을 리스트 형태로 저장
re.compile('[ㄱ-ㅎ]+').findall(text) # 출력 ['ㅋㅋㅋ']

import re

text = "ㅋㅋㅋ 안녕하ㅏ세요"
# 정규식에서 일치되는 부분을 리스트 형태로 저장
re.compile('[ㄱ-ㅎ|ㅏ-ㅣ]+').findall(text) # 출력 ['ㅋㅋㅋ', 'ㅏ']

import re

text = "ㅋㅋㅋ 안녕하세요"
# 정규식에서 일치되는 부분을 리스트 형태로 저장
re.compile('[가-힣]+').findall(text) # 출력 ['안녕하세요']

정규식에서 일치되는 부분을 제외하고 추출

import re

text = "ㅋㅋㅋ 안녕하세요"
# 한글과 띄어쓰기을 제외하고 모든 글자 (자음, 모음만 있는경우 제외)
re.compile('[ |가-힣]+').sub('', text) # 출력 'ㅋㅋㅋ'


text = "하이 ㅋㅋㅋ 안녕하ㅏ세요"
# 정규식에서 일치되는 부분을  제외하고 저장
re.compile('[ |ㄱ-ㅎ|ㅏ-ㅣ]+').sub('',text) # 출력 '안녕하세요'

주의해야할 점

  • 주의해야 할 점은 두개의 결과가 리스트str으로 반환된다는 점이다.
  • 아래 예제를 통해서 내가 언제 어떤 상황에서 어떻게 처리해야할지 판단하면 된다.
import re

text = "ㅋㅋㅋ 안녕하ㅏ세요"
# 정규식에서 일치되는 부분을 리스트 형태로 저장
re.compile('[가-힣]+').findall(text) # 출력 ['안녕하', '세요']
text = "하이 ㅋㅋㅋ 안녕하ㅏ세요"
# 정규식에서 일치되는 부분을  제외하고 저장
re.compile('[ |ㄱ-ㅎ|ㅏ-ㅣ]+').sub('',text) # 출력 '안녕하세요'

+ Recent posts